Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/keenwrite.git
A .gitattributes
1
# always use LF line endings
2
3
# ALL FILES:
4
#   Normalize line endings to LF on checkin and
5
#   prevent conversion to CRLF when the file is checked out.
6
7
* text eol=lf
8
9
10
# BINARY FILES:
11
#   Disable line ending normalize on checkin.
12
13
*.blend binary
14
15
*.bin binary
16
*.bmp binary
17
*.eps binary
18
*.exe binary
19
*.gif binary
20
*.jar binary
21
*.jpg binary
22
*.mng binary
23
*.png binary
24
*.zip binary
25
*.otf binary
26
*.ttf binary
27
128
A .github/ISSUE_TEMPLATE/bug_report.md
1
---
2
name: Bug report
3
about: Create a report to help us improve
4
title: ''
5
labels: bug
6
assignees: ''
7
8
---
9
10
**Description**
11
A concise problem description.
12
13
**Replicate**
14
Exact and complete steps to reproduce the problem 100% of the time:
15
16
1. Open '...'
17
1. Click '....'
18
1. Click '....'
19
20
**Expected**
21
Describe the expected behaviour.
22
23
**Actual**
24
Describe the actual behaviour.
25
26
**Screenshots**
27
Add screenshots to show the problem, if applicable.
28
29
**Environment**
30
 - Operating System: (Windows, Linux, Mac)
31
 - Application: e.g., 1.7.16
32
33
**Details**
34
Add additional information, if applicable.
135
A .gitignore
1
dist
2
*.bin
3
*.exe
4
/*.jar
5
build
6
.gradle
7
contacted.csv
8
video
9
.settings
10
.classpath
11
.idea
12
themes
113
A .project
1
<?xml version="1.0" encoding="UTF-8"?>
2
<projectDescription>
3
	<name>Markdown Writer FX</name>
4
	<comment></comment>
5
	<projects>
6
	</projects>
7
	<buildSpec>
8
		<buildCommand>
9
			<name>org.eclipse.jdt.core.javabuilder</name>
10
			<arguments>
11
			</arguments>
12
		</buildCommand>
13
		<buildCommand>
14
			<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
15
			<arguments>
16
			</arguments>
17
		</buildCommand>
18
	</buildSpec>
19
	<natures>
20
		<nature>org.eclipse.jdt.core.javanature</nature>
21
		<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
22
	</natures>
23
	<filteredResources>
24
		<filter>
25
			<id>1438449113801</id>
26
			<name></name>
27
			<type>26</type>
28
			<matcher>
29
				<id>org.eclipse.ui.ide.multiFilter</id>
30
				<arguments>1.0-projectRelativePath-matches-false-false-build</arguments>
31
			</matcher>
32
		</filter>
33
		<filter>
34
			<id>1438449113801</id>
35
			<name></name>
36
			<type>26</type>
37
			<matcher>
38
				<id>org.eclipse.ui.ide.multiFilter</id>
39
				<arguments>1.0-projectRelativePath-matches-false-false-.gradle</arguments>
40
			</matcher>
41
		</filter>
42
	</filteredResources>
43
</projectDescription>
144
A BUILD.md
1
# Introduction
2
3
This document describes how to build the application and platform binaries.
4
5
# Requirements
6
7
Download and install the following software packages:
8
9
* [JDK 16](https://bell-sw.com/pages/downloads/?version=java-16) (Full JDK + JavaFX)
10
* [Gradle 7.0](https://services.gradle.org/distributions)
11
* [Git 2.28.0](https://git-scm.com/downloads)
12
13
## Repository
14
15
Clone the repository as follows:
16
17
    git clone https://github.com/DaveJarvis/keenwrite.git
18
19
The repository is cloned.
20
21
# Build
22
23
Build the application überjar as follows:
24
25
    cd keenwrite
26
    gradle clean jar
27
28
The application is built.
29
30
# Run
31
32
After the application is compiled, run it as follows:
33
34
    java --illegal-access=permit -jar build/libs/keenwrite.jar
35
36
On Windows:
37
38
    java --illegal-access=permit -jar build\libs\keenwrite.jar
39
40
# Integrated development environments
41
42
This section describes setup instructions to import and run the application using an integrated development environment (IDE). Running the application should trigger a build.
43
44
## IntelliJ IDEA
45
46
This section describes how to build and run the application using IntellIJ's IDEA.
47
48
### Import
49
50
Complete the following steps to import the application:
51
52
1. Start the IDE.
53
1. Click **File → New → Project from Existing Sources**.
54
1. Browse to the directory containing `keenwrite`.
55
1. Click **OK**.
56
1. Select **Gradle** as the external model.
57
1. Click **Finish**.
58
59
The project is imported into the IDE.
60
61
### Configure
62
63
Configure the IDE to run the application as follows:
64
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.
71
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.
79
80
# Installers
81
82
This section describes how to set up the development environment and build native executables for supported operating systems.
83
84
## Setup
85
86
Follow these one-time setup instructions to begin:
87
88
1. Ensure `$HOME/bin` is set in the `PATH` environment variable.
89
1. Copy `build-template` into `$HOME/bin`.
90
91
Setup is complete.
92
93
## Binaries
94
95
Run the `installer` script to build platform-specific binaries, such as:
96
97
    ./installer -V -o linux
98
99
The `installer` script:
100
101
* downloads a JDK;
102
* generates a run script;
103
* bundles the JDK, run script, and JAR file; and
104
* creates a standalone binary, so no installation required.
105
106
Run `./installer -h` to see all command-line options.
107
108
# Releases
109
110
After installing `scripts/build-template`, build release binaries as follows:
111
112
    git tag -a 2.0.0 -m "Release name"
113
    git push origin --tags
114
    ./release.sh
115
116
When finished, browse to the project releases page to draft a new release.
117
118
# Versioning
119
120
Version numbers are read directly from Git using a plugin. The version number is written to `app.properties` in the `resources` directory. The application reads that file to display version information upon start.
121
1122
A CODE_OF_CONDUCT.md
1
# Contributor Covenant Code of Conduct
2
3
## Our Pledge
4
5
In the interest of fostering an open and welcoming environment, we as
6
contributors and maintainers pledge to making participation in our project and
7
our community a harassment-free experience for everyone, regardless of age, body
8
size, disability, ethnicity, sex characteristics, gender identity and expression,
9
level of experience, education, socio-economic status, nationality, personal
10
appearance, race, religion, or sexual identity and orientation.
11
12
## Our Standards
13
14
Examples of behavior that contributes to creating a positive environment
15
include:
16
17
* Using welcoming and inclusive language
18
* Being respectful of differing viewpoints and experiences
19
* Gracefully accepting constructive criticism
20
* Focusing on what is best for the community
21
* Showing empathy towards other community members
22
23
Examples of unacceptable behavior by participants include:
24
25
* The use of sexualized language or imagery and unwelcome sexual attention or
26
 advances
27
* Trolling, insulting/derogatory comments, and personal or political attacks
28
* Public or private harassment
29
* Publishing others' private information, such as a physical or electronic
30
 address, without explicit permission
31
* Other conduct which could reasonably be considered inappropriate in a
32
 professional setting
33
34
## Our Responsibilities
35
36
Project maintainers are responsible for clarifying the standards of acceptable
37
behavior and are expected to take appropriate and fair corrective action in
38
response to any instances of unacceptable behavior.
39
40
Project maintainers have the right and responsibility to remove, edit, or
41
reject comments, commits, code, wiki edits, issues, and other contributions
42
that are not aligned to this Code of Conduct, or to ban temporarily or
43
permanently any contributor for other behaviors that they deem inappropriate,
44
threatening, offensive, or harmful.
45
46
## Scope
47
48
This Code of Conduct applies both within project spaces and in public spaces
49
when an individual is representing the project or its community. Examples of
50
representing a project or community include using an official project e-mail
51
address, posting via an official social media account, or acting as an appointed
52
representative at an online or offline event. Representation of a project may be
53
further defined and clarified by project maintainers.
54
55
## Enforcement
56
57
Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
reported by contacting the project team at Dave.Jarvis@gmail.com. All
59
complaints will be reviewed and investigated and will result in a response that
60
is deemed necessary and appropriate to the circumstances. The project team is
61
obligated to maintain confidentiality with regard to the reporter of an incident.
62
Further details of specific enforcement policies may be posted separately.
63
64
Project maintainers who do not follow or enforce the Code of Conduct in good
65
faith may face temporary or permanent repercussions as determined by other
66
members of the project's leadership.
67
68
## Attribution
69
70
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72
73
[homepage]: https://www.contributor-covenant.org
74
75
For answers to common questions about this code of conduct, see
76
https://www.contributor-covenant.org/faq
177
A LICENSE.md
1
# License
2
3
Copyright 2020All rights reserved.
4
5
Redist
6
Copyright 2015 Karl Tauber
7
tribution and use in source and binary forms, with or without
8
modification, are permitted provided that the following conditions are met:
19
A R/README.md
1
# R Functions
2
3
Import the files in this directory into the application, which include:
4
5
* pluralize.R
6
* possessive.R
7
* conversion.R
8
* csv.R
9
10
# pluralize.R
11
12
This file defines a function that implements most of Damian Conway's [An Algorithmic Approach to English Pluralization](http://blob.perl.org/tpc/1998/User_Applications/Algorithmic%20Approach%20Plurals/Algorithmic_Plurals.html).
13
14
## Usage
15
16
Example usages of the pluralize function include:
17
18
    `r#pluralize( 'mouse' )` - mice
19
    `r#pluralize( 'buzz' )` - buzzes
20
    `r#pluralize( 'bus' )` - busses
21
22
# possessive.R
23
24
This file defines a function that applies possessives to English words.
25
26
## Usage
27
28
Example usages of the possessive function include:
29
30
    `r#pos( 'Ross' )` - Ross'
31
    `r#pos( 'Ruby' )` - Ruby's
32
    `r#pos( 'Lois' )` - Lois'
33
    `r#pos( 'my' )` - mine
34
    `r#pos( 'Your' )` - Yours
35
136
A R/bootstrap.R
1
setwd( '{{application.r.working.directory}}' )
2
assign( "anchor", '{{date.anchor}}', envir = .GlobalEnv )
3
4
source( 'pluralize.R' )
5
source( 'possessive.R' )
6
source( 'conversion.R' )
7
source( 'csv.R' )
8
19
A R/conversion.R
1
1
# -----------------------------------------------------------------------------
2
# Copyright 2020, White Magic Software, Ltd.
3
# 
4
# Permission is hereby granted, free of charge, to any person obtaining
5
# a copy of this software and associated documentation zzz
A R/csv.R
1
# -----------------------------------------------------------------------------
2
# Copyright 2020, White Magic Software, Ltd.
3
# 
4
# Permission is hereby granted, free of charge, to any person obtaining
5
# a copy of this software and associated documentation files -----------------------------------------------------------------------------
16
7
# -----------------------------------------------------------------------------# -----------------------------------------------------------------------------2s 
A R/pluralize.R
1
# -----------------------------------------------------------------------------
2
# Copyright 2020, White Magic Software, Ltd.
3
# 
4
# Permission is hereby granted, free of charge, to any person obtaining
5
# a copy of this software and associated documentation files -----------------------------------------------------------------------------
16
7
# ----------------------------------------------------------------------------- -----------------------------------------------------------------------------es|zz|x|, -zz, -x, -[aeiou]y11. Change -[aeiou]y to -y2. Change -y to -ix. Change -z to -zzze-----------------------------------------------------------------------------# ----------------------------------------------------------------------------------------------------------------------------------------------------------# ----------------------------------------------------------------------------------------------------------------------------------------------------------# -----------------------------------------------------------------------------
8
    "Bhutanese",
9
    "bison",
10
    "bream",
11
    "Burmese",
12
    "carp",
13
    "chassis",
14
    "Chinese",
15
    "clippers",
16
    "cod",
17
    "contretemps",
18
    "corps",
19
    "debris",
20
    "djinn",
21
    "eland",
22
    "elk",
23
    "flounder",
24
    "fracas",
25
    "gallows",
26
    "graffiti",
27
    "headquarters",
28
   
29
    "hovercraft",
30
    "innings",
31
    "Japanese",
32
    "Lebanese",
33
    "mackerel",
34
    "means",
35
    "mews",
36
    "mice",
37
    "mumps",
38
   
39
    "pliers",
40
    "Portuguese",
41
    "proceedings",
42
    "salmon",
43
    "scissors",
44
    "sea-bass",
45
    "Senegalese",
46
    "shears",
47
   
48
    "spacecraft",
49
    "swine",
50
    "trout",
51
    "tuna",
52
    "Vietnamese",
53
    "watercraft",
54
    "whiting",
55
    "wildebeest"
56
  -----------------------------------------------------------------------------# -----------------------------------------------------------------------------
57
pl.is-----------------------------------------------------------------------------# ----------------------------------------------------------------------------------------------------------------------------------------------------------# -----------------------------------------------------------------------------
A R/possessive.R
1
# -----------------------------------------------------------------------------
2
# Copyright 2020, White Magic Software, Ltd.
3
# 
4
# Permission is hereby granted, free of charge, to any person obtaining
5
# a copy of this software and associated documentation Returns leftmost n characters of slstr <- function( s, n = 1 ) {
6
  substr( s, 0, n )
7
}
8
9
# -----------------------------------------------------------------------------
10
# Returns rightmost n characters of srstr <- function( s, n = 1 ) {
11
  l <- nchar( s )
12
  substr( s, l - n + 1, l )
13
}
14
15
# -----------------------------------------------------------------------------
16
# Returns the possessive form of the given word, spos <- function( s ) {
17
  lcs <- tolower( s )
18
  pronouns <- c( 'your', 'our', 'her', 'it', 'their' )
19
20
  if( lcs == 'my' ) {
21
    # Change "[Mm]y" to "[Mm]ine".
22
    s <- paste0( lstr( s, 1 ), "ine" )
23
  }
24
  else if( lcs %in% pronouns ) {
25
    # Append an s to most pronouns.
26
    s <- paste0( s, 's' )
27
  }
28
  else if( lcs != 'his' ) {
29
    # Possessive for all other words except 'his'.
30
    s <- paste0( s, ifelse( rstr( s, 1 ) == 's', "'" ,"'s" ) )
31
  }
32
33
  s
34
}
35
136
A README.md
1
1
![Total Downloads](https://img.shields.io/github/downloads/DaveJarvis/keenwrite/total?color=blue&label=Total%20Downloads&style=flat) ![Release Downloads](https://img.shields.io/github/downloads/DaveJarvis/keenwrite/latest/total?color=purple&label=Release%RE&package=jre-fullHigh-quality PDF exportSee [screenshots](docs/screenshots.md) for visuals.
A README.zh-CN.md
1
# ![Logo](docs/images/app-title.zh-CN.png)
2
3
智能写入是一个文本编辑器,它使用插值字符串引用外部定义的值。
4
5
## 下载
6
7
下载以下版本之一:
8
9
* [Windows](https://gitreleases.dev/gh/latest/keenwrite.exe)
10
* [Linux](https://gitreleases.dev/gh/latest/keenwrite.bin)
11
* [Java Archive](https://gitreleases.dev/gh/latest/keenwrite.jar)
12
13
## 跑
14
15
在第一次运行期间,应用程序将自身解压到�Other
16
17
Download and install a full version of [OpenJDK 15/?version=java-15#mn) that includes JavaFX module support, then run:
18
19
``` bash
20
java -jar keenwrite.jar
21
```
22
23
## 特征
24
25
* 用户使用XSLT3或更早版本的XML文档转换软件使用
26
27
See the [detailed documentation](docs/README.md) for information about
28
using the application.
29
30
## 截图
131
32
![Graph
A build.gradle
1
plugins {
2
  id 'application'
3
  id 'org.openjfx.javafxplugin' version '0.0.10'
4
  id 'com.palantir.git-version' version '0.12.3'
5
}
6
7
repositories {
8
  mavenCentral()
9
  jcenter()
10
11
  maven {
12
    url 'https://oss.sonatype.odef moduleSecurity]final Propertiesnal File configFile = 
13
final FileInputStream configStream = new FileInputStream(configFile)
14
config.load(configStream)
15
configStream.close()
16
17
final String applicationName = config.get("application.title").toString().toLowerCase()
18
final String applicationClass = "com.${applicatiapplication {
19
  mainClass.set(applicationClass)moduleSecurity
20
}
21
22
version = gitVersion()
123
24
final FiledoFirst {
25
    manifest {
26
  applicationClass
27
    }moduleSecurity
A docs/README.md
1
# Documentation
2
3
The following documents have additional details about using the editor:
14
5
* [div.md](div.md) -- Syntax for annotated text (fenced divs)
6
* [i18n.md](i18n.md) -- Internationalization features
A docs/credits.md
1
# Credits
12
3
* Karl Tauber: [Markdown Writer FX](https://github.com/JFormDesigner/markdown-writer-fx)
4
* Tomas Mikula: [RichTextFX](https://github.com/TomasMikula/RichTextFX), [ReactFX](h
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/diagram.md
1
# Introduction
2
3
From a high level, the application architecture for converting Markdown documents is captured in the following figure:
4
5
``` diagram-graphviz
6
digraph {
7
  node [fontname = "Noto Sans" fontsize=6 height=.25 penwidth=.5];
8
  edge [fontname = "Noto Sans" fontsize=6  penwidth=.5 arrowsize=.5];
9
  node [shape=box color="{{keenwrite.palette.primary.light}}" fontcolor="{{keenwrite.palette.primary.dark}}"]
10
  edge [color="{{keenwrite.palette.grayscale.light}}" fontcolor="{{keenwrite.palette.grayscale.dark}}"]
11
12
  {{keenwrite.classes.processors.variable.definition}} ->   {{keenwrite.classes.processors.markdown}} [xlabel="{{keenwrite.graph.label.chain.next}}  "]
13
  {{keenwrite.classes.processors.markdown}} -> {{keenwrite.classes.processors.preview}} [xlabel="{{keenwrite.graph.label.chain.next}}  "]
14
  {{keenwrite.classes.processors.markdown}} -> Extensions [label="  contains"]
15
16
Extensions -> FencedBlockExtension
17
Extensions -> CaretExtension
18
Extensions -> ImageLinkExtension
19
Extensions -> TeXExtension
20
}
21
```
22
23
An extension is an addition to the Markdown parser, flexmark-java, that is used when converting the document's abstract syntax tree into an HTML document. The {{keenwrite.classes.processors.markdown}} contains both prepackaged and custom extensions.
124
A docs/diagram.yaml
1
---
2
keenwrite:
3
  classes:
4
    processors:
5
      markdown: MarkdownProcessor
6
      variable:
7
        definition: DefinitionProcessor
8
      preview: PreviewProcessor
9
  palette:
10
    primary:
11
      light: '#51a9cf'
12
      dark: '#126d95'
13
    secondary:
14
      light: '#ec706a'
15
      dark: '#7e252f'
16
    accent:
17
      light: '#76A786'
18
      dark: '#385742'
19
    grayscale:
20
      light: '#bac2c5'
21
      dark: '#394343'
22
  graph:
23
    label:
24
      chain:
25
        next: successor
126
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
```
115
16
To start a fenced div, begin a lss
A docs/i18n.md
1
# Internationalization
2
3
The application supports internationalization (I18N). There are multiple
4
components to editing and previewing internationalized text documents.
5
These include:
6
7
* Fonts
8
* Language
19
10
Both fonts and language must be set for non-Latin-bepanel usesfonts
A docs/images/app-ide.png
Binary file
A docs/images/app-title.png
Binary file
A docs/images/app-title.zh-CN.png
Binary file
A docs/images/architecture/architecture.png
Binary file
A docs/images/architecture/architecture.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
   inkscape:export-ydpi="150.0097"
11
   inkscape:export-xdpi="150.0097"
12
   sodipodi:docname="architecture.svg"
13
   viewBox="0 0 764.4414 811.46748"
14
   height="811.46747"
15
   width="764.44141"
16
   id="svg4610"
17
   version="1.2"
18
   inkscape:version="1.0 (4035a4fb49, 2020-05-01)">
19
  <metadata
20
     id="metadata4616">
21
    <rdf:RDF>
22
      <cc:Work
23
         rdf:about="">
24
        <dc:format>image/svg+xml</dc:format>
25
        <dc:type
26
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
27
        <dc:title />
28
      </cc:Work>
29
    </rdf:RDF>
30
  </metadata>
31
  <defs
32
     id="defs4614">
33
    <marker
34
       inkscape:stockid="Arrow1Mend"
35
       orient="auto"
36
       refY="0"
37
       refX="0"
38
       id="marker10933"
39
       style="overflow:visible"
40
       inkscape:isstock="true">
41
      <path
42
         id="path10931"
43
         d="M 0,0 5,-5 -12.5,0 5,5 Z"
44
         style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1"
45
         transform="matrix(-0.4,0,0,-0.4,-4,0)"
46
         inkscape:connector-curvature="0" />
47
    </marker>
48
    <marker
49
       inkscape:stockid="Arrow1Mend"
50
       orient="auto"
51
       refY="0"
52
       refX="0"
53
       id="marker9893"
54
       style="overflow:visible"
55
       inkscape:isstock="true">
56
      <path
57
         id="path9891"
58
         d="M 0,0 5,-5 -12.5,0 5,5 Z"
59
         style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1"
60
         transform="matrix(-0.4,0,0,-0.4,-4,0)"
61
         inkscape:connector-curvature="0" />
62
    </marker>
63
    <marker
64
       inkscape:collect="always"
65
       inkscape:isstock="true"
66
       style="overflow:visible"
67
       id="marker9767"
68
       refX="0"
69
       refY="0"
70
       orient="auto"
71
       inkscape:stockid="Arrow1Mend">
72
      <path
73
         inkscape:connector-curvature="0"
74
         transform="matrix(-0.4,0,0,-0.4,-4,0)"
75
         style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1"
76
         d="M 0,0 5,-5 -12.5,0 5,5 Z"
77
         id="path9765" />
78
    </marker>
79
    <marker
80
       inkscape:collect="always"
81
       inkscape:stockid="Arrow1Mend"
82
       orient="auto"
83
       refY="0"
84
       refX="0"
85
       id="marker9761"
86
       style="overflow:visible"
87
       inkscape:isstock="true">
88
      <path
89
         id="path9759"
90
         d="M 0,0 5,-5 -12.5,0 5,5 Z"
91
         style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1"
92
         transform="matrix(-0.4,0,0,-0.4,-4,0)"
93
         inkscape:connector-curvature="0" />
94
    </marker>
95
    <marker
96
       inkscape:isstock="true"
97
       style="overflow:visible"
98
       id="marker9750"
99
       refX="0"
100
       refY="0"
101
       orient="auto"
102
       inkscape:stockid="Arrow1Mend">
103
      <path
104
         inkscape:connector-curvature="0"
105
         transform="matrix(-0.4,0,0,-0.4,-4,0)"
106
         style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1"
107
         d="M 0,0 5,-5 -12.5,0 5,5 Z"
108
         id="path9748" />
109
    </marker>
110
    <marker
111
       inkscape:isstock="true"
112
       style="overflow:visible"
113
       id="marker9715"
114
       refX="0"
115
       refY="0"
116
       orient="auto"
117
       inkscape:stockid="Arrow1Mend">
118
      <path
119
         inkscape:connector-curvature="0"
120
         transform="matrix(-0.4,0,0,-0.4,-4,0)"
121
         style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1"
122
         d="M 0,0 5,-5 -12.5,0 5,5 Z"
123
         id="path9713" />
124
    </marker>
125
    <marker
126
       inkscape:collect="always"
127
       inkscape:stockid="Arrow1Mend"
128
       orient="auto"
129
       refY="0"
130
       refX="0"
131
       id="marker9685"
132
       style="overflow:visible"
133
       inkscape:isstock="true">
134
      <path
135
         id="path9683"
136
         d="M 0,0 5,-5 -12.5,0 5,5 Z"
137
         style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1"
138
         transform="matrix(-0.4,0,0,-0.4,-4,0)"
139
         inkscape:connector-curvature="0" />
140
    </marker>
141
    <marker
142
       inkscape:collect="always"
143
       inkscape:stockid="Arrow1Mend"
144
       orient="auto"
145
       refY="0"
146
       refX="0"
147
       id="marker9679"
148
       style="overflow:visible"
149
       inkscape:isstock="true">
150
      <path
151
         id="path9677"
152
         d="M 0,0 5,-5 -12.5,0 5,5 Z"
153
         style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1"
154
         transform="matrix(-0.4,0,0,-0.4,-4,0)"
155
         inkscape:connector-curvature="0" />
156
    </marker>
157
    <marker
158
       inkscape:collect="always"
159
       inkscape:isstock="true"
160
       style="overflow:visible"
161
       id="marker9640"
162
       refX="0"
163
       refY="0"
164
       orient="auto"
165
       inkscape:stockid="Arrow1Mend">
166
      <path
167
         inkscape:connector-curvature="0"
168
         transform="matrix(-0.4,0,0,-0.4,-4,0)"
169
         style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1"
170
         d="M 0,0 5,-5 -12.5,0 5,5 Z"
171
         id="path9638" />
172
    </marker>
173
    <marker
174
       inkscape:collect="always"
175
       inkscape:isstock="true"
176
       style="overflow:visible"
177
       id="marker9513"
178
       refX="0"
179
       refY="0"
180
       orient="auto"
181
       inkscape:stockid="Arrow1Mend">
182
      <path
183
         inkscape:connector-curvature="0"
184
         transform="matrix(-0.4,0,0,-0.4,-4,0)"
185
         style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1"
186
         d="M 0,0 5,-5 -12.5,0 5,5 Z"
187
         id="path9511" />
188
    </marker>
189
    <marker
190
       inkscape:stockid="Arrow1Mend"
191
       orient="auto"
192
       refY="0"
193
       refX="0"
194
       id="marker9509"
195
       style="overflow:visible"
196
       inkscape:isstock="true">
197
      <path
198
         id="path9507"
199
         d="M 0,0 5,-5 -12.5,0 5,5 Z"
200
         style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1"
201
         transform="matrix(-0.4,0,0,-0.4,-4,0)"
202
         inkscape:connector-curvature="0" />
203
    </marker>
204
    <marker
205
       inkscape:isstock="true"
206
       style="overflow:visible"
207
       id="marker9505"
208
       refX="0"
209
       refY="0"
210
       orient="auto"
211
       inkscape:stockid="Arrow1Mend">
212
      <path
213
         inkscape:connector-curvature="0"
214
         transform="matrix(-0.4,0,0,-0.4,-4,0)"
215
         style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1"
216
         d="M 0,0 5,-5 -12.5,0 5,5 Z"
217
         id="path9503" />
218
    </marker>
219
    <marker
220
       inkscape:collect="always"
221
       inkscape:stockid="Arrow1Mend"
222
       orient="auto"
223
       refY="0"
224
       refX="0"
225
       id="marker9479"
226
       style="overflow:visible"
227
       inkscape:isstock="true">
228
      <path
229
         id="path9477"
230
         d="M 0,0 5,-5 -12.5,0 5,5 Z"
231
         style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke:#05556e;stroke-width:1.00000003pt;stroke-opacity:1"
232
         transform="matrix(-0.4,0,0,-0.4,-4,0)"
233
         inkscape:connector-curvature="0" />
234
    </marker>
235
    <clipPath
236
       id="ID000001">
237
      <rect
238
         id="rect6"
239
         height="961.125"
240
         width="1381.6169"
241
         y="-43.688"
242
         x="-62.683998" />
243
    </clipPath>
244
    <filter
245
       id="filter2842"
246
       inkscape:label="Drop Shadow"
247
       style="color-interpolation-filters:sRGB;">
248
      <feFlood
249
         id="feFlood2832"
250
         result="flood"
251
         flood-color="rgb(0,0,0)"
252
         flood-opacity="0.498039" />
253
      <feComposite
254
         id="feComposite2834"
255
         result="composite1"
256
         operator="in"
257
         in2="SourceGraphic"
258
         in="flood" />
259
      <feGaussianBlur
260
         id="feGaussianBlur2836"
261
         result="blur"
262
         stdDeviation="2"
263
         in="composite1" />
264
      <feOffset
265
         id="feOffset2838"
266
         result="offset"
267
         dy="3"
268
         dx="3" />
269
      <feComposite
270
         id="feComposite2840"
271
         result="composite2"
272
         operator="over"
273
         in2="offset"
274
         in="SourceGraphic" />
275
    </filter>
276
    <filter
277
       id="filter2854"
278
       inkscape:label="Drop Shadow"
279
       style="color-interpolation-filters:sRGB;">
280
      <feFlood
281
         id="feFlood2844"
282
         result="flood"
283
         flood-color="rgb(0,0,0)"
284
         flood-opacity="0.498039" />
285
      <feComposite
286
         id="feComposite2846"
287
         result="composite1"
288
         operator="in"
289
         in2="SourceGraphic"
290
         in="flood" />
291
      <feGaussianBlur
292
         id="feGaussianBlur2848"
293
         result="blur"
294
         stdDeviation="2"
295
         in="composite1" />
296
      <feOffset
297
         id="feOffset2850"
298
         result="offset"
299
         dy="3"
300
         dx="3" />
301
      <feComposite
302
         id="feComposite2852"
303
         result="composite2"
304
         operator="over"
305
         in2="offset"
306
         in="SourceGraphic" />
307
    </filter>
308
    <filter
309
       id="filter2866"
310
       inkscape:label="Drop Shadow"
311
       style="color-interpolation-filters:sRGB;">
312
      <feFlood
313
         id="feFlood2856"
314
         result="flood"
315
         flood-color="rgb(0,0,0)"
316
         flood-opacity="0.498039" />
317
      <feComposite
318
         id="feComposite2858"
319
         result="composite1"
320
         operator="in"
321
         in2="SourceGraphic"
322
         in="flood" />
323
      <feGaussianBlur
324
         id="feGaussianBlur2860"
325
         result="blur"
326
         stdDeviation="2"
327
         in="composite1" />
328
      <feOffset
329
         id="feOffset2862"
330
         result="offset"
331
         dy="3"
332
         dx="3" />
333
      <feComposite
334
         id="feComposite2864"
335
         result="composite2"
336
         operator="over"
337
         in2="offset"
338
         in="SourceGraphic" />
339
    </filter>
340
    <filter
341
       id="filter2878"
342
       inkscape:label="Drop Shadow"
343
       style="color-interpolation-filters:sRGB;">
344
      <feFlood
345
         id="feFlood2868"
346
         result="flood"
347
         flood-color="rgb(0,0,0)"
348
         flood-opacity="0.498039" />
349
      <feComposite
350
         id="feComposite2870"
351
         result="composite1"
352
         operator="in"
353
         in2="SourceGraphic"
354
         in="flood" />
355
      <feGaussianBlur
356
         id="feGaussianBlur2872"
357
         result="blur"
358
         stdDeviation="2"
359
         in="composite1" />
360
      <feOffset
361
         id="feOffset2874"
362
         result="offset"
363
         dy="3"
364
         dx="3" />
365
      <feComposite
366
         id="feComposite2876"
367
         result="composite2"
368
         operator="over"
369
         in2="offset"
370
         in="SourceGraphic" />
371
    </filter>
372
    <filter
373
       id="filter2890"
374
       inkscape:label="Drop Shadow"
375
       style="color-interpolation-filters:sRGB;">
376
      <feFlood
377
         id="feFlood2880"
378
         result="flood"
379
         flood-color="rgb(0,0,0)"
380
         flood-opacity="0.498039" />
381
      <feComposite
382
         id="feComposite2882"
383
         result="composite1"
384
         operator="in"
385
         in2="SourceGraphic"
386
         in="flood" />
387
      <feGaussianBlur
388
         id="feGaussianBlur2884"
389
         result="blur"
390
         stdDeviation="2"
391
         in="composite1" />
392
      <feOffset
393
         id="feOffset2886"
394
         result="offset"
395
         dy="3"
396
         dx="3" />
397
      <feComposite
398
         id="feComposite2888"
399
         result="composite2"
400
         operator="over"
401
         in2="offset"
402
         in="SourceGraphic" />
403
    </filter>
404
    <filter
405
       id="filter2902"
406
       inkscape:label="Drop Shadow"
407
       style="color-interpolation-filters:sRGB;">
408
      <feFlood
409
         id="feFlood2892"
410
         result="flood"
411
         flood-color="rgb(0,0,0)"
412
         flood-opacity="0.498039" />
413
      <feComposite
414
         id="feComposite2894"
415
         result="composite1"
416
         operator="in"
417
         in2="SourceGraphic"
418
         in="flood" />
419
      <feGaussianBlur
420
         id="feGaussianBlur2896"
421
         result="blur"
422
         stdDeviation="2"
423
         in="composite1" />
424
      <feOffset
425
         id="feOffset2898"
426
         result="offset"
427
         dy="3"
428
         dx="3" />
429
      <feComposite
430
         id="feComposite2900"
431
         result="composite2"
432
         operator="over"
433
         in2="offset"
434
         in="SourceGraphic" />
435
    </filter>
436
    <filter
437
       id="filter2914"
438
       inkscape:label="Drop Shadow"
439
       style="color-interpolation-filters:sRGB;">
440
      <feFlood
441
         id="feFlood2904"
442
         result="flood"
443
         flood-color="rgb(0,0,0)"
444
         flood-opacity="0.498039" />
445
      <feComposite
446
         id="feComposite2906"
447
         result="composite1"
448
         operator="in"
449
         in2="SourceGraphic"
450
         in="flood" />
451
      <feGaussianBlur
452
         id="feGaussianBlur2908"
453
         result="blur"
454
         stdDeviation="2"
455
         in="composite1" />
456
      <feOffset
457
         id="feOffset2910"
458
         result="offset"
459
         dy="3"
460
         dx="3" />
461
      <feComposite
462
         id="feComposite2912"
463
         result="composite2"
464
         operator="over"
465
         in2="offset"
466
         in="SourceGraphic" />
467
    </filter>
468
    <filter
469
       id="filter2926"
470
       inkscape:label="Drop Shadow"
471
       style="color-interpolation-filters:sRGB;">
472
      <feFlood
473
         id="feFlood2916"
474
         result="flood"
475
         flood-color="rgb(0,0,0)"
476
         flood-opacity="0.498039" />
477
      <feComposite
478
         id="feComposite2918"
479
         result="composite1"
480
         operator="in"
481
         in2="SourceGraphic"
482
         in="flood" />
483
      <feGaussianBlur
484
         id="feGaussianBlur2920"
485
         result="blur"
486
         stdDeviation="2"
487
         in="composite1" />
488
      <feOffset
489
         id="feOffset2922"
490
         result="offset"
491
         dy="3"
492
         dx="3" />
493
      <feComposite
494
         id="feComposite2924"
495
         result="composite2"
496
         operator="over"
497
         in2="offset"
498
         in="SourceGraphic" />
499
    </filter>
500
    <filter
501
       id="filter2938"
502
       inkscape:label="Drop Shadow"
503
       style="color-interpolation-filters:sRGB;">
504
      <feFlood
505
         id="feFlood2928"
506
         result="flood"
507
         flood-color="rgb(0,0,0)"
508
         flood-opacity="0.498039" />
509
      <feComposite
510
         id="feComposite2930"
511
         result="composite1"
512
         operator="in"
513
         in2="SourceGraphic"
514
         in="flood" />
515
      <feGaussianBlur
516
         id="feGaussianBlur2932"
517
         result="blur"
518
         stdDeviation="2"
519
         in="composite1" />
520
      <feOffset
521
         id="feOffset2934"
522
         result="offset"
523
         dy="3"
524
         dx="3" />
525
      <feComposite
526
         id="feComposite2936"
527
         result="composite2"
528
         operator="over"
529
         in2="offset"
530
         in="SourceGraphic" />
531
    </filter>
532
    <filter
533
       id="filter2950"
534
       inkscape:label="Drop Shadow"
535
       style="color-interpolation-filters:sRGB;">
536
      <feFlood
537
         id="feFlood2940"
538
         result="flood"
539
         flood-color="rgb(0,0,0)"
540
         flood-opacity="0.498039" />
541
      <feComposite
542
         id="feComposite2942"
543
         result="composite1"
544
         operator="in"
545
         in2="SourceGraphic"
546
         in="flood" />
547
      <feGaussianBlur
548
         id="feGaussianBlur2944"
549
         result="blur"
550
         stdDeviation="2"
551
         in="composite1" />
552
      <feOffset
553
         id="feOffset2946"
554
         result="offset"
555
         dy="3"
556
         dx="3" />
557
      <feComposite
558
         id="feComposite2948"
559
         result="composite2"
560
         operator="over"
561
         in2="offset"
562
         in="SourceGraphic" />
563
    </filter>
564
    <filter
565
       id="filter2962"
566
       inkscape:label="Drop Shadow"
567
       style="color-interpolation-filters:sRGB;">
568
      <feFlood
569
         id="feFlood2952"
570
         result="flood"
571
         flood-color="rgb(0,0,0)"
572
         flood-opacity="0.498039" />
573
      <feComposite
574
         id="feComposite2954"
575
         result="composite1"
576
         operator="in"
577
         in2="SourceGraphic"
578
         in="flood" />
579
      <feGaussianBlur
580
         id="feGaussianBlur2956"
581
         result="blur"
582
         stdDeviation="2"
583
         in="composite1" />
584
      <feOffset
585
         id="feOffset2958"
586
         result="offset"
587
         dy="3"
588
         dx="3" />
589
      <feComposite
590
         id="feComposite2960"
591
         result="composite2"
592
         operator="over"
593
         in2="offset"
594
         in="SourceGraphic" />
595
    </filter>
596
    <filter
597
       id="filter2974"
598
       inkscape:label="Drop Shadow"
599
       style="color-interpolation-filters:sRGB;">
600
      <feFlood
601
         id="feFlood2964"
602
         result="flood"
603
         flood-color="rgb(0,0,0)"
604
         flood-opacity="0.498039" />
605
      <feComposite
606
         id="feComposite2966"
607
         result="composite1"
608
         operator="in"
609
         in2="SourceGraphic"
610
         in="flood" />
611
      <feGaussianBlur
612
         id="feGaussianBlur2968"
613
         result="blur"
614
         stdDeviation="2"
615
         in="composite1" />
616
      <feOffset
617
         id="feOffset2970"
618
         result="offset"
619
         dy="3"
620
         dx="3" />
621
      <feComposite
622
         id="feComposite2972"
623
         result="composite2"
624
         operator="over"
625
         in2="offset"
626
         in="SourceGraphic" />
627
    </filter>
628
    <filter
629
       id="filter2986"
630
       inkscape:label="Drop Shadow"
631
       style="color-interpolation-filters:sRGB;">
632
      <feFlood
633
         id="feFlood2976"
634
         result="flood"
635
         flood-color="rgb(0,0,0)"
636
         flood-opacity="0.498039" />
637
      <feComposite
638
         id="feComposite2978"
639
         result="composite1"
640
         operator="in"
641
         in2="SourceGraphic"
642
         in="flood" />
643
      <feGaussianBlur
644
         id="feGaussianBlur2980"
645
         result="blur"
646
         stdDeviation="2"
647
         in="composite1" />
648
      <feOffset
649
         id="feOffset2982"
650
         result="offset"
651
         dy="3"
652
         dx="3" />
653
      <feComposite
654
         id="feComposite2984"
655
         result="composite2"
656
         operator="over"
657
         in2="offset"
658
         in="SourceGraphic" />
659
    </filter>
660
  </defs>
661
  <sodipodi:namedview
662
     inkscape:snap-text-baseline="false"
663
     inkscape:document-rotation="0"
664
     fit-margin-bottom="20"
665
     fit-margin-right="20"
666
     fit-margin-left="20"
667
     fit-margin-top="20"
668
     inkscape:current-layer="svg4610"
669
     inkscape:cy="370.55742"
670
     inkscape:cx="398.61418"
671
     inkscape:zoom="1.3753763"
672
     showgrid="false"
673
     id="namedview4612"
674
     inkscape:window-height="1280"
675
     inkscape:window-width="2055"
676
     inkscape:pageshadow="2"
677
     inkscape:pageopacity="1"
678
     guidetolerance="10"
679
     gridtolerance="10"
680
     objecttolerance="10"
681
     borderopacity="1"
682
     bordercolor="#666666"
683
     pagecolor="#ffffff"
684
     inkscape:window-x="215"
685
     inkscape:window-y="26"
686
     inkscape:window-maximized="0" />
687
  <path
688
     sodipodi:nodetypes="ccssssc"
689
     inkscape:connector-curvature="0"
690
     style="fill:#333333;fill-opacity:0.0666667;fill-rule:nonzero;stroke:#df4d65;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
691
     d="M 53.35547,445.11522 V 790.96744 H 741.0332 c 1.6112,0 2.90821,-1.29701 2.90821,-2.9082 V 448.02342 c 0,-1.6112 -1.297,-2.9082 -2.90821,-2.9082 z"
692
     id="path9961" />
693
  <path
694
     sodipodi:nodetypes="sssccssss"
695
     id="path9940"
696
     d="m 20.5,787.82486 c 0,0.87013 0.35019,1.65683 0.91797,2.22461 0.56778,0.56778 1.35253,0.91797 2.22265,0.91797 H 53.35547 V 445.11522 H 23.64062 c -0.87012,0 -1.65487,0.35019 -2.22265,0.91797 -0.56778,0.56778 -0.91797,1.35254 -0.91797,2.22266 z"
697
     style="fill:#df4d65;fill-opacity:1;fill-rule:nonzero;stroke:#df4d65;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
698
     inkscape:connector-curvature="0" />
699
  <path
700
     sodipodi:nodetypes="sssccssss"
701
     id="path11125"
702
     d="m 20.5,423.31014 c 0,0.87013 0.35019,1.65683 0.91797,2.22461 0.56778,0.56778 1.354494,0.9764 2.22265,0.91797 H 53.35547 V 210.6005 H 23.64062 c -0.87012,0 -1.65487,0.3502 -2.22265,0.918 C 20.85019,212.08629 20.5,212.871 20.5,213.74109 Z"
703
     style="fill:#3e3e3e;fill-opacity:1;fill-rule:nonzero;stroke:#3e3e3e;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
704
     inkscape:connector-curvature="0" />
705
  <path
706
     sodipodi:nodetypes="ccssssc"
707
     inkscape:connector-curvature="0"
708
     style="fill:#333333;fill-opacity:0.0666667;fill-rule:nonzero;stroke:#3e3e3e;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
709
     d="m 53.35547,210.6005 v 215.85222 h 687.67774 c 1.6112,0 2.9082,-1.29701 2.9082,-2.9082 V 213.5087 c 0,-1.6112 -1.29701,-2.90352 -2.9082,-2.9082 z"
710
     id="path11123" />
711
  <path
712
     id="path6150"
713
     d="m 557.756,222.53493 c -0.87012,0 -1.65683,0.35019 -2.22461,0.91797 -0.56778,0.56778 -0.91797,1.35253 -0.91797,2.22265 v 29.71485 h 165.6211 v -29.71485 c 0,-0.87012 -0.35019,-1.65487 -0.91797,-2.22265 -0.56778,-0.56778 -1.35254,-0.91797 -2.22266,-0.91797 z"
714
     style="fill:#c53bd7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2926)"
715
     inkscape:connector-curvature="0"
716
     sodipodi:nodetypes="sssccssss" />
717
  <path
718
     sodipodi:nodetypes="ccssssc"
719
     id="path6134"
720
     d="m 720.75716,255.39041 h -165.6211 v 152.63392 c 0,1.6112 1.29701,2.90821 2.90821,2.90821 h 159.80469 c 1.6112,0 2.9082,-1.29701 2.9082,-2.90821 z"
721
     style="fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2926)"
722
     inkscape:connector-curvature="0" />
723
  <path
724
     id="path6082"
725
     d="m 317.13559,222.53494 c -0.87011,0 -1.65683,0.35019 -2.2246,0.91797 -0.56779,0.56778 -0.91798,1.35253 -0.91798,2.22265 v 29.71485 h 165.62111 v -29.71485 c 0,-0.87012 -0.35019,-1.65487 -0.91798,-2.22265 -0.56778,-0.56778 -1.35254,-0.91797 -2.22266,-0.91797 z"
726
     style="fill:#3dd092;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2938)"
727
     inkscape:connector-curvature="0"
728
     sodipodi:nodetypes="sssccssss" />
729
  <path
730
     sodipodi:nodetypes="ccssssc"
731
     id="path6080"
732
     d="M 479.61412,255.39041 H 313.99301 v 152.63392 c 0,1.6112 1.29701,2.90821 2.90821,2.90821 h 159.80469 c 1.6112,0 2.90821,-1.29701 2.90821,-2.90821 z"
733
     style="fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2938)"
734
     inkscape:connector-curvature="0" />
735
  <path
736
     id="path10980"
737
     d="M 53.35547,20.500012 V 188.35224 h 687.67774 c 1.6112,0 2.9082,-1.29701 2.9082,-2.9082 V 23.408212 c 0,-1.6112 -1.29701,-2.912886 -2.9082,-2.9082 z"
738
     style="fill:#333333;fill-opacity:0.0666667;fill-rule:nonzero;stroke:#3e3e3e;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
739
     inkscape:connector-curvature="0"
740
     sodipodi:nodetypes="ccssssc" />
741
  <path
742
     inkscape:connector-curvature="0"
743
     style="fill:#3e3e3e;fill-opacity:1;fill-rule:nonzero;stroke:#3e3e3e;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
744
     d="m 20.5,185.20966 c 0,0.87013 0.35019,1.65683 0.91797,2.22461 0.56778,0.56778 1.35253,0.91797 2.22265,0.91797 H 53.35547 V 20.500012 H 23.64062 c -0.87012,0 -1.65487,0.350201 -2.22265,0.918 -0.56778,0.5678 -0.91797,1.3525 -0.91797,2.2226 z"
745
     id="path10982"
746
     sodipodi:nodetypes="sssccssss" />
747
  <path
748
     sodipodi:nodetypes="sssccssss"
749
     inkscape:connector-curvature="0"
750
     style="fill:#c53bd7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2962)"
751
     d="m 557.75599,36.704447 c -0.87012,0 -1.65683,0.35019 -2.22461,0.91797 -0.56778,0.56778 -0.91797,1.35253 -0.91797,2.22265 v 29.71485 h 165.6211 v -29.71485 c 0,-0.87012 -0.35019,-1.65487 -0.91797,-2.22265 -0.56778,-0.56778 -1.35254,-0.91797 -2.22266,-0.91797 z"
752
     id="path4857" />
753
  <path
754
     inkscape:connector-curvature="0"
755
     style="fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2962)"
756
     d="M 720.23451,69.559917 H 554.61341 V 169.2396 c 0,1.6112 1.29701,2.90821 2.90821,2.90821 h 159.80469 c 1.6112,0 2.9082,-1.29701 2.9082,-2.90821 z"
757
     id="path4853" />
758
  <path
759
     sodipodi:nodetypes="sssccssss"
760
     inkscape:connector-curvature="0"
761
     style="fill:#3dd092;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2974)"
762
     d="m 317.13558,36.704447 c -0.87011,0 -1.65683,0.35019 -2.2246,0.91797 -0.56779,0.56778 -0.91798,1.35253 -0.91798,2.22265 v 29.71485 h 165.62111 v -29.71485 c 0,-0.87012 -0.35019,-1.65487 -0.91798,-2.22265 -0.56778,-0.56778 -1.35254,-0.91797 -2.22266,-0.91797 z"
763
     id="path5726" />
764
  <path
765
     inkscape:connector-curvature="0"
766
     style="fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2974)"
767
     d="M 479.61411,69.559917 H 313.993 V 169.2396 c 0,1.6112 1.29701,2.90821 2.90821,2.90821 H 476.7059 c 1.6112,0 2.90821,-1.29701 2.90821,-2.90821 z"
768
     id="path5724" />
769
  <path
770
     id="path4721"
771
     d="m 235.85308,44.704447 c 0.87012,0 1.65488,0.35019 2.22266,0.91797 0.56778,0.56778 0.91797,1.35253 0.91797,2.22265 v -0.23242 c 0,-1.6112 -1.297,-2.9082 -2.9082,-2.9082 z"
772
     style="opacity:1;fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.21841836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
773
     inkscape:connector-curvature="0" />
774
  <path
775
     sodipodi:nodetypes="sssccssss"
776
     id="path4719"
777
     d="m 76.515197,36.704447 c -0.870125,0 -1.656831,0.35019 -2.22461,0.91797 -0.567778,0.56778 -0.917968,1.35253 -0.917968,2.22265 v 29.71485 H 238.99371 v -29.71485 c 0,-0.87012 -0.35019,-1.65487 -0.91797,-2.22265 -0.56778,-0.56778 -1.35254,-0.91797 -2.22266,-0.91797 z"
778
     style="fill:#46c7f0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2986)"
779
     inkscape:connector-curvature="0" />
780
  <path
781
     id="path4723"
782
     d="M 238.99372,69.559917 H 73.372613 V 169.2396 c 0,1.6112 1.29701,2.90821 2.90821,2.90821 H 236.08552 c 1.6112,0 2.9082,-1.29701 2.9082,-2.90821 z"
783
     style="fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2986)"
784
     inkscape:connector-curvature="0" />
785
  <path
786
     id="rect4622"
787
     d="m 76.280822,44.704447 c -1.611195,0 -2.908203,1.297 -2.908203,2.9082 v 0.23242 c 0,-0.87012 0.35019,-1.65487 0.917968,-2.22265 0.567779,-0.56778 1.354485,-0.91797 2.22461,-0.91797 z"
788
     style="opacity:1;fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.21841836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
789
     inkscape:connector-curvature="0" />
790
  <path
791
     sodipodi:nodetypes="cc"
792
     inkscape:connector-curvature="0"
793
     id="path9889"
794
     d="m 397.61301,500.62068 -0.50618,32.59418"
795
     style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:1.9694221;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9893)" />
796
  <path
797
     style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9715)"
798
     d="m 554.61351,648.83688 -69.6817,47.69253"
799
     id="path9711"
800
     inkscape:connector-curvature="0"
801
     sodipodi:nodetypes="cc" />
802
  <path
803
     sodipodi:nodetypes="cc"
804
     inkscape:connector-curvature="0"
805
     id="path9675"
806
     d="M 554.61351,567.95047 484.93181,615.643"
807
     style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9679)" />
808
  <rect
809
     ry="3.9839513"
810
     rx="3.9205718"
811
     y="537.09552"
812
     x="554.61353"
813
     height="32.855"
814
     width="165.621"
815
     id="rect9618"
816
     style="opacity:1;fill:#c53bd7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.02355671;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2842)" />
817
  <rect
818
     ry="3.9839513"
819
     rx="3.9205718"
820
     y="537.09552"
821
     x="73.372665"
822
     height="32.855"
823
     width="165.621"
824
     id="rect9614"
825
     style="opacity:1;fill:#46c7f0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.02355671;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2914)" />
826
  <path
827
     inkscape:connector-curvature="0"
828
     style="opacity:1;fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.21841836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
829
     d="m 235.85308,545.09525 c 0.87012,0 1.65488,0.35019 2.22266,0.91797 0.56778,0.56778 0.91797,1.35253 0.91797,2.22265 v -0.23242 c 0,-1.6112 -1.297,-2.9082 -2.9082,-2.9082 z"
830
     id="path9323" />
831
  <path
832
     inkscape:connector-curvature="0"
833
     style="opacity:1;fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.21841836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
834
     d="m 76.280823,545.09525 c -1.611195,0 -2.908203,1.297 -2.908203,2.9082 v 0.23242 c 0,-0.87012 0.35019,-1.65487 0.917968,-2.22265 0.567779,-0.56778 1.354485,-0.91797 2.22461,-0.91797 z"
835
     id="path9327" />
836
  <rect
837
     style="opacity:1;fill:#3dd092;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.02355671;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2902)"
838
     id="rect9616"
839
     width="165.621"
840
     height="32.855"
841
     x="313.99307"
842
     y="537.09552"
843
     rx="3.9205718"
844
     ry="3.9839513" />
845
  <path
846
     sodipodi:nodetypes="cc"
847
     inkscape:connector-curvature="0"
848
     id="path9491"
849
     d="m 240.99257,554.11276 65.23376,-1.01307"
850
     style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9513)" />
851
  <path
852
     style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9640)"
853
     d="m 481.61298,554.11276 65.23376,-1.01307"
854
     id="path9501"
855
     inkscape:connector-curvature="0"
856
     sodipodi:nodetypes="cc" />
857
  <rect
858
     ry="3.9839513"
859
     rx="3.9205718"
860
     y="617.79578"
861
     x="313.99307"
862
     height="32.855"
863
     width="165.621"
864
     id="rect9620"
865
     style="opacity:1;fill:#3dd092;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.02355671;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2890)" />
866
  <path
867
     sodipodi:nodetypes="cc"
868
     inkscape:connector-curvature="0"
869
     id="path9681"
870
     d="m 481.61298,634.81299 65.23376,-1.01307"
871
     style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9685)" />
872
  <rect
873
     style="opacity:1;fill:#c53bd7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.02355671;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2854)"
874
     id="rect9687"
875
     width="165.621"
876
     height="32.855"
877
     x="554.61353"
878
     y="617.79578"
879
     rx="3.9205718"
880
     ry="3.9839513" />
881
  <path
882
     style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9750)"
883
     d="m 481.61298,715.51321 65.23376,-1.01307"
884
     id="path9734"
885
     inkscape:connector-curvature="0"
886
     sodipodi:nodetypes="cc" />
887
  <rect
888
     ry="3.9839513"
889
     rx="3.9205718"
890
     y="698.49591"
891
     x="554.61353"
892
     height="32.855"
893
     width="165.621"
894
     id="rect9736"
895
     style="opacity:1;fill:#c53bd7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.02355671;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2866)" />
896
  <path
897
     id="path9830"
898
     d="m 356.40451,489.45323 c -0.80426,0 -1.45167,0.64741 -1.45167,1.45166 v 0.11602 c 0,-0.43433 0.1748,-0.82605 0.45822,-1.10946 0.28341,-0.28342 0.6761,-0.45822 1.11043,-0.45822 z"
899
     style="opacity:1;fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.10902636;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
900
     inkscape:connector-curvature="0" />
901
  <rect
902
     style="opacity:1;fill:#ffb73a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.9391377;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
903
     id="rect9826"
904
     width="120.98324"
905
     height="24"
906
     x="336.82672"
907
     y="477.86002"
908
     rx="2.8639088"
909
     ry="2.9102066" />
910
  <path
911
     id="path10514"
912
     d="m 235.85301,637.23875 c 0.87012,0 1.65488,0.35019 2.22266,0.91797 0.56778,0.56778 0.91797,1.35253 0.91797,2.22265 v -0.23242 c 0,-1.6112 -1.297,-2.9082 -2.9082,-2.9082 z"
913
     style="opacity:1;fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.21841836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
914
     inkscape:connector-curvature="0" />
915
  <rect
916
     style="opacity:1;fill:#3dd092;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.02355671;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2878)"
917
     id="rect9717"
918
     width="165.621"
919
     height="32.855"
920
     x="313.99307"
921
     y="698.49591"
922
     rx="3.9205718"
923
     ry="3.9839513" />
924
  <path
925
     id="path10537"
926
     d="M 238.99366,636.97465 H 73.372671 V 729.175 c 0,1.2055 0.970418,2.17592 2.175911,2.17592 H 236.81776 c 1.20549,0 2.1759,-0.97042 2.1759,-2.17592 z"
927
     style="opacity:1;fill:#333333;fill-opacity:0.93333333;fill-rule:nonzero;stroke:none;stroke-width:0.16342013;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
928
     inkscape:connector-curvature="0"
929
     sodipodi:nodetypes="ccssssc" />
930
  <path
931
     sodipodi:nodetypes="sssccssss"
932
     id="path10516"
933
     d="m 75.723937,612.39226 c -0.651025,0 -1.239637,0.26201 -1.664447,0.68682 -0.424811,0.42482 -0.686822,1.01196 -0.686822,1.66299 v 22.23258 H 238.99366 v -22.23258 c 0,-0.65103 -0.26201,-1.23817 -0.68682,-1.66299 -0.42481,-0.42481 -1.01197,-0.68682 -1.66299,-0.68682 z"
934
     style="opacity:1;fill:#ffb73a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.16342013;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
935
     inkscape:connector-curvature="0" />
936
  <path
937
     style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker10933)"
938
     d="m 240.99257,715.51318 65.23376,-1.01307"
939
     id="path10929"
940
     inkscape:connector-curvature="0"
941
     sodipodi:nodetypes="cc" />
942
  <path
943
     style="fill:#df4d65;fill-opacity:1;fill-rule:evenodd;stroke-width:0.05250736"
944
     d="m 399.47357,99.155037 -0.12716,0.0127 -0.12716,0.0141 -0.12574,0.0141 -0.12716,0.0155 -0.61883,0.967813 -0.29106,0.9325 -0.17943,0.91977 -0.1215,1.09073 -0.30943,0.0636 -0.308,0.0678 -0.308,0.0735 -0.30801,0.0763 -0.58069,-0.93108 -0.5609,-0.75023 -0.66687,-0.71349 -0.97912,-0.6033 -0.12009,0.0409 -0.1201,0.0424 -0.12009,0.0424 -0.12009,0.0424 -0.38854,1.08085 -0.0763,0.97487 0.0297,0.93673 0.12575,1.08932 -0.28823,0.1314 -0.28681,0.13563 -0.28398,0.13987 -0.28117,0.14271 -0.77425,-0.77849 -0.7149,-0.60612 -0.80816,-0.54819 -1.0879,-0.37017 -0.10879,0.0678 -0.10738,0.0679 -0.10738,0.0678 -0.10738,0.0678 -0.13846,1.14018 0.14129,0.9664 0.23735,0.90706 0.36594,1.03563 -0.25149,0.19215 -0.24865,0.19497 -0.24585,0.19922 -0.24442,0.20204 -0.92825,-0.58634 -0.83077,-0.43234 -0.90988,-0.35463 -1.14301,-0.11868 -0.0904,0.0904 -0.0904,0.089 -0.089,0.0904 -0.0904,0.0904 0.11868,1.14301 0.35462,0.90988 0.43234,0.83218 0.58634,0.92684 -0.20204,0.24442 -0.19921,0.24584 -0.19498,0.24867 -0.19215,0.25148 -1.03563,-0.36593 -0.90705,-0.23736 -0.96641,-0.14128 -1.14018,0.13845 -0.0678,0.10738 -0.0678,0.10738 -0.0678,0.10738 -0.0678,0.10879 0.37016,1.0879 0.5482,0.80816 0.60612,0.71491 0.77848,0.77425 -0.1427,0.28117 -0.13987,0.28398 -0.13564,0.28681 -0.13139,0.28823 -1.09073,-0.12575 -0.93532,-0.0297 -0.97487,0.0763 -1.08084,0.38854 -0.0424,0.12009 -0.0424,0.12009 -0.0424,0.1201 -0.0409,0.12009 0.6033,0.97912 0.7135,0.66686 0.75023,0.56091 0.93107,0.58069 -0.0763,0.30801 -0.0735,0.308 -0.0678,0.308 -0.0636,0.30942 -1.09073,0.1215 -0.91977,0.17944 -0.9325,0.29105 -0.96781,0.61883 -0.0156,0.12717 -0.0141,0.12574 -0.0141,0.12716 -0.0127,0.12716 0.80533,0.81804 0.84348,0.49168 0.85619,0.38006 1.03704,0.36028 -0.006,0.31648 -0.003,0.31648 0.003,0.31648 0.006,0.31648 -1.03704,0.35887 -0.85619,0.38006 -0.84348,0.49168 -0.80533,0.81946 0.0127,0.12716 0.0141,0.12574 0.0141,0.12716 0.0156,0.12574 0.96781,0.62026 0.9325,0.29104 0.91977,0.17944 1.09073,0.12009 0.0636,0.30942 0.0678,0.30941 0.0735,0.30801 0.0763,0.30659 -0.93107,0.5821 -0.75023,0.56091 -0.7135,0.66687 -0.6033,0.97771 0.0409,0.12008 0.0424,0.12151 0.0424,0.1201 0.0424,0.11868 1.08084,0.38995 0.97487,0.0763 0.93532,-0.0297 1.09073,-0.12574 0.13139,0.28822 0.13564,0.2854 0.13987,0.28399 0.1427,0.28257 -0.77848,0.77425 -0.60612,0.7135 -0.5482,0.80957 -0.37016,1.08791 0.0678,0.10737 0.0678,0.10879 0.0678,0.10738 0.0678,0.10738 1.14018,0.13846 0.96641,-0.1427 0.90705,-0.23736 1.03563,-0.36452 0.19215,0.25149 0.19498,0.24866 0.19921,0.24584 0.20204,0.24302 -0.58634,0.92825 -0.43234,0.83076 -0.35462,0.9113 -0.11868,1.14159 0.0904,0.0918 0.089,0.089 0.0904,0.0904 0.0904,0.089 1.14301,-0.11868 0.90988,-0.35321 0.83077,-0.43375 0.92825,-0.58493 0.24442,0.20204 0.24585,0.19921 0.24865,0.19497 0.25149,0.19216 -0.36594,1.03563 -0.23735,0.90564 -0.14129,0.9664 0.13846,1.14018 0.10738,0.0692 0.10738,0.0678 0.10738,0.0678 0.10879,0.0664 1.0879,-0.37017 0.80816,-0.54677 0.7149,-0.60754 0.77425,-0.77708 0.28117,0.14271 0.28398,0.13987 0.28681,0.13422 0.28823,0.13139 -0.12575,1.09074 -0.0297,0.93673 0.0763,0.97346 0.38854,1.08084 0.12009,0.0438 0.12009,0.0424 0.1201,0.041 0.12009,0.0409 0.97912,-0.60188 0.66687,-0.71349 0.5609,-0.75165 0.58069,-0.93108 0.30801,0.0777 0.308,0.072 0.308,0.0692 0.30943,0.0636 0.1215,1.09073 0.17943,0.91978 0.29106,0.93249 0.61883,0.9664 0.12716,0.0156 0.12574,0.0141 0.12716,0.0141 0.12716,0.0141 0.81806,-0.80533 0.49167,-0.8449 0.38006,-0.85619 0.36028,-1.03704 0.31648,0.007 0.31648,0.003 0.31649,-0.003 0.31648,-0.007 0.36028,1.03704 0.37865,0.85619 0.49167,0.8449 0.81947,0.80533 0.12715,-0.0141 0.12574,-0.0141 0.12717,-0.0141 0.12574,-0.0156 0.62025,-0.9664 0.29104,-0.93249 0.17944,-0.91978 0.12009,-1.09073 0.30942,-0.0636 0.30942,-0.0692 0.30799,-0.072 0.3066,-0.0777 0.58211,0.93108 0.5609,0.75165 0.66687,0.71349 0.97771,0.60188 0.12009,-0.0409 0.1215,-0.041 0.1201,-0.0424 0.11868,-0.0438 0.38995,-1.08084 0.0763,-0.97346 -0.0297,-0.93673 -0.12574,-1.09074 0.28822,-0.13139 0.2854,-0.13422 0.28398,-0.13987 0.28258,-0.14271 0.77424,0.77708 0.7135,0.60754 0.80957,0.54677 1.08791,0.37017 0.10737,-0.0664 0.10879,-0.0678 0.10738,-0.0678 0.10738,-0.0692 0.13847,-1.14018 -0.14271,-0.9664 -0.23737,-0.90564 -0.36452,-1.03563 0.25149,-0.19216 0.24866,-0.19497 0.24585,-0.19921 0.24301,-0.20204 0.92825,0.58493 0.83077,0.43375 0.91129,0.35321 1.1416,0.11868 0.0904,-0.089 0.0904,-0.0904 0.0904,-0.089 0.089,-0.0918 -0.11868,-1.14159 -0.35321,-0.9113 -0.43375,-0.83076 -0.58492,-0.92825 0.20203,-0.24302 0.19921,-0.24584 0.19498,-0.24866 0.19215,-0.25149 1.03563,0.36452 0.90564,0.23736 0.9664,0.1427 1.14018,-0.13846 0.0692,-0.10738 0.0678,-0.10738 0.0678,-0.10879 0.0664,-0.10737 -0.37017,-1.08791 -0.54677,-0.80957 -0.60754,-0.7135 -0.77706,-0.77425 0.1427,-0.28257 0.13986,-0.28399 0.13423,-0.2854 0.13139,-0.28822 1.09073,0.12574 0.93674,0.0297 0.97345,-0.0763 1.08085,-0.38995 0.0438,-0.11868 0.0424,-0.1201 0.0409,-0.12151 0.041,-0.12008 -0.6019,-0.97771 -0.71349,-0.66687 -0.75164,-0.56091 -0.93108,-0.5821 0.0777,-0.30659 0.072,-0.30801 0.0692,-0.30941 0.0636,-0.30942 1.09073,-0.12009 0.91978,-0.17944 0.93249,-0.29104 0.9664,-0.62026 0.0155,-0.12574 0.0141,-0.12716 0.0141,-0.12574 0.0141,-0.12716 -0.80533,-0.81946 -0.8449,-0.49168 -0.85619,-0.38006 -1.03704,-0.35887 0.007,-0.31648 0.003,-0.31648 -0.003,-0.31648 -0.007,-0.31648 1.03704,-0.36028 0.85619,-0.38006 0.8449,-0.49168 0.80533,-0.81804 -0.0141,-0.12716 -0.0141,-0.12716 -0.0141,-0.12574 -0.0155,-0.12717 -0.9664,-0.61883 -0.93249,-0.29105 -0.91978,-0.17944 -1.09073,-0.1215 -0.0636,-0.30942 -0.0692,-0.308 -0.072,-0.308 -0.0777,-0.30801 0.93108,-0.58069 0.75164,-0.56091 0.71349,-0.66686 0.6019,-0.97912 -0.041,-0.12009 -0.0409,-0.1201 -0.0424,-0.12009 -0.0438,-0.12009 -1.08085,-0.38854 -0.97345,-0.0763 -0.93674,0.0297 -1.09073,0.12575 -0.13139,-0.28823 -0.13423,-0.28681 -0.13986,-0.28398 -0.1427,-0.28117 0.77706,-0.77425 0.60754,-0.71491 0.54677,-0.80816 0.37017,-1.0879 -0.0664,-0.10879 -0.0678,-0.10738 -0.0678,-0.10738 -0.0692,-0.10738 -1.14018,-0.13845 -0.9664,0.14128 -0.90564,0.23736 -1.03563,0.36593 -0.19215,-0.25148 -0.19498,-0.24867 -0.19921,-0.24584 -0.20203,-0.24442 0.58492,-0.92684 0.43375,-0.83218 0.35321,-0.90988 0.11868,-1.14301 -0.089,-0.0904 -0.0904,-0.0904 -0.0904,-0.089 -0.0904,-0.0904 -1.1416,0.11868 -0.91129,0.35463 -0.83077,0.43234 -0.92825,0.58634 -0.24301,-0.20204 -0.24585,-0.19922 -0.24866,-0.19497 -0.25149,-0.19215 0.36452,-1.03563 0.23737,-0.90706 0.14271,-0.9664 -0.13847,-1.14018 -0.10738,-0.0678 -0.10738,-0.0678 -0.10879,-0.0679 -0.10737,-0.0678 -1.08791,0.37017 -0.80957,0.54819 -0.7135,0.60612 -0.77424,0.77849 -0.28258,-0.14271 -0.28398,-0.13987 -0.2854,-0.13563 -0.28822,-0.1314 0.12574,-1.08932 0.0297,-0.93673 -0.0763,-0.97487 -0.38995,-1.08085 -0.11868,-0.0424 -0.1201,-0.0424 -0.1215,-0.0424 -0.12009,-0.0409 -0.97771,0.6033 -0.66687,0.71349 -0.5609,0.75023 -0.58211,0.93108 -0.3066,-0.0763 -0.30799,-0.0735 -0.30942,-0.0678 -0.30942,-0.0636 -0.12009,-1.09073 -0.17944,-0.91977 -0.29104,-0.9325 -0.62025,-0.967813 -0.12574,-0.0155 -0.12717,-0.0141 -0.12574,-0.0141 -0.12715,-0.0127 -0.81947,0.80533 -0.49167,0.843483 -0.37865,0.8562 -0.36028,1.03704 -0.31648,-0.006 -0.31649,-0.003 -0.31648,0.003 -0.31648,0.006 -0.36028,-1.03704 -0.38006,-0.8562 -0.49167,-0.843483 z m 2.68302,20.688573 a 5.3990039,5.3990039 0 0 1 5.39856,5.39997 5.3990039,5.3990039 0 0 1 -5.39856,5.39855 5.3990039,5.3990039 0 0 1 -5.39996,-5.39855 5.3990039,5.3990039 0 0 1 5.39996,-5.39997 z"
945
     id="path5693"
946
     inkscape:connector-curvature="0" />
947
  <path
948
     inkscape:connector-curvature="0"
949
     d="m 380.9529,101.31918 a 4.37599,4.37599 0 0 1 -4.37599,4.37599 4.37599,4.37599 0 0 1 -4.37599,-4.37599 4.37599,4.37599 0 0 1 4.37599,-4.375983 4.37599,4.37599 0 0 1 4.37599,4.375983 z m 4.63493,-1.27213 c -0.32212,-0.118873 -0.95326,0.0926 -0.92258,-0.401293 -0.13877,-0.39635 -0.21401,-0.74537 0.27363,-0.88946 0.78055,-0.47633 1.45123,-1.16128 1.74461,-2.04171 0.15411,-0.39145 -0.3432,-0.48754 -0.63657,-0.53536 -0.91614,-0.25589 -1.86519,0.0578 -2.73328,0.35995 -0.11023,-0.31345 -0.69059,-0.56868 -0.47901,-0.88657 0.56405,-0.84324 0.99162,-1.8335 0.85012,-2.86709 -0.031,-0.41955 -0.52073,-0.29038 -0.8058,-0.20618 -0.93646,0.16692 -1.65537,0.86143 -2.30642,1.51029 -0.23528,-0.23464 -0.86896,-0.21274 -0.81624,-0.59097 0.14241,-1.00446 0.0978,-2.08217 -0.47806,-2.95201 -0.20995,-0.36459 -0.59514,-0.0357 -0.81544,0.16385 -0.7713,0.55671 -1.11768,1.49434 -1.42274,2.36143 -0.3138,-0.10927 -0.87519,0.18536 -0.99181,-0.17826 -0.30757,-0.96675 -0.81528,-1.91841 -1.71153,-2.45229 -0.34734,-0.23737 -0.55176,0.22606 -0.66364,0.50149 -0.45331,0.83622 -0.35865,1.83127 -0.25723,2.74482 -0.33012,0.0378 -0.70817,0.54672 -0.97098,0.26977 -0.69651,-0.73763 -1.56687,-1.37476 -2.60601,-1.46682 -0.41593,-0.0631 -0.39904,0.443 -0.38034,0.73971 -0.0456,0.95009 0.47143,1.80554 0.95918,2.58463 -0.28104,0.17725 -0.40076,0.79984 -0.75777,0.6643 -0.94759,-0.36236 -2.00818,-0.55864 -2.98437,-0.1908 -0.40215,0.12357 -0.16723,0.57227 -0.0217,0.83147 0.37114,0.8758 1.2081,1.42221 1.98561,1.91248 -0.17632,0.28163 -0.0141,0.89453 -0.39449,0.92732 -1.01097,0.0847 -2.05173,0.367983 -2.77166,1.122963 -0.3087,0.2858 0.0976,0.58816 0.34122,0.75853 0.71439,0.62804 1.70558,0.75716 2.6188,0.8616 -0.0367,0.33025 0.37548,0.81204 0.0469,1.00665 -0.87415,0.51488 -1.68886,1.22174 -2.00994,2.2143 -0.15411,0.39144 0.3432,0.48753 0.63657,0.53535 0.91612,0.25589 1.86516,-0.0578 2.73323,-0.35995 0.11029,0.31341 0.69063,0.56869 0.47905,0.88657 -0.56412,0.8432 -0.99155,1.83352 -0.85015,2.86709 0.031,0.41952 0.52075,0.2904 0.80584,0.20618 0.93644,-0.16692 1.65537,-0.86139 2.30637,-1.51029 0.2353,0.23464 0.86901,0.21272 0.81629,0.59098 -0.14241,1.00446 -0.0978,2.08215 0.47802,2.95202 0.20997,0.36455 0.59517,0.0357 0.81548,-0.16387 0.77125,-0.55674 1.11768,-1.49435 1.42274,-2.36142 0.31379,0.10926 0.8752,-0.18537 0.99181,0.17824 0.30754,0.96678 0.81527,1.91842 1.71153,2.45229 0.34733,0.23738 0.55172,-0.22608 0.66362,-0.50146 0.45335,-0.83621 0.35866,-1.83128 0.25725,-2.74484 0.33011,-0.0378 0.70812,-0.54672 0.97093,-0.26977 0.69656,0.7376 1.5669,1.37477 2.60606,1.46683 0.41593,0.0632 0.39897,-0.44304 0.38032,-0.73972 0.0457,-0.95011 -0.4715,-1.8055 -0.95916,-2.58463 0.28105,-0.17722 0.40074,-0.79983 0.75772,-0.6643 0.94761,0.36234 2.00821,0.55865 2.98442,0.1908 0.40215,-0.12357 0.16723,-0.57228 0.0217,-0.83146 -0.37116,-0.87579 -1.20814,-1.42218 -1.98561,-1.91249 0.17632,-0.28163 0.0141,-0.89453 0.39449,-0.92732 1.01097,-0.0847 2.05173,-0.36799 2.77166,-1.12295 0.3087,-0.28581 -0.0976,-0.58817 -0.34122,-0.75854 -0.47483,-0.43652 -1.13407,-0.61787 -1.75144,-0.75008 z"
950
     style="fill:#05556e;fill-opacity:1;fill-rule:evenodd;stroke-width:0.04014921"
951
     id="path5687" />
952
  <path
953
     style="fill:#05556e;fill-opacity:1;stroke-width:0.11881336"
954
     id="path4816"
955
     d="m 619.92265,90.37586 h 2.72717 v 2.71445 h 2.51374 v -2.71445 h 2.72716 v 8.21477 h -2.72716 v -2.73825 h -2.49003 v 2.73825 h -2.75088 m 11.57268,-5.47651 h -2.40702 v -2.73826 h 7.55307 v 2.73826 h -2.41888 v 5.47651 h -2.72717 m 6.34363,-8.21477 h 2.8576 l 1.75487,2.89303 1.75487,-2.89303 h 2.8576 v 8.21477 h -2.72717 v -4.07167 l -1.90901,2.95256 -1.90902,-2.95256 v 4.07167 h -2.67974 m 10.57667,-8.21477 h 2.72717 v 5.50033 h 3.86546 v 2.71444 h -6.59263"
956
     inkscape:connector-curvature="0" />
957
  <path
958
     id="path4818"
959
     d="m 619.82779,146.45062 -3.91289,-44.09786 h 43.01811 l -3.91289,44.07405 -17.63174,4.90505"
960
     inkscape:connector-curvature="0"
961
     style="fill:#e44d26;stroke-width:0.11881336" />
962
  <path
963
     id="path4820"
964
     d="m 637.42396,147.58164 v -41.60962 h 17.5843 l -3.3556,37.62129"
965
     inkscape:connector-curvature="0"
966
     style="fill:#f16529;stroke-width:0.11881336" />
967
  <path
968
     id="path4822"
969
     d="m 623.90669,111.3652 h 13.51727 v 5.40508 h -7.61236 l 0.498,5.53605 h 7.11436 v 5.39318 h -12.04697 m 0.23714,2.71444 h 5.40691 l 0.37943,4.32169 6.02349,1.61914 v 5.64319 L 626.373,138.90255"
970
     inkscape:connector-curvature="0"
971
     style="fill:#ebebeb;stroke-width:0.11881336" />
972
  <path
973
     id="path4824"
974
     d="m 650.89379,111.3652 h -13.49355 v 5.40508 h 12.99555 m -0.48615,5.53605 h -12.5094 v 5.40508 h 6.64006 l -0.62843,7.02423 -6.01163,1.61914 v 5.61938 l 11.02724,-3.07161"
975
     inkscape:connector-curvature="0"
976
     style="fill:#ffffff;stroke-width:0.11881336" />
977
  <path
978
     sodipodi:nodetypes="cc"
979
     inkscape:connector-curvature="0"
980
     id="path5804"
981
     d="m 240.99252,105.07517 65.2338,-1.01308"
982
     style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9479)" />
983
  <path
984
     style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9505)"
985
     d="m 481.61302,105.07517 65.2337,-1.01308"
986
     id="path9497"
987
     inkscape:connector-curvature="0"
988
     sodipodi:nodetypes="cc" />
989
  <path
990
     inkscape:connector-curvature="0"
991
     style="opacity:1;fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.21841836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
992
     d="m 235.85308,230.53494 c 0.87012,0 1.65488,0.35019 2.22266,0.91797 0.56778,0.56778 0.91797,1.35253 0.91797,2.22265 v -0.23242 c 0,-1.6112 -1.297,-2.9082 -2.9082,-2.9082 z"
993
     id="path6102" />
994
  <path
995
     inkscape:connector-curvature="0"
996
     style="opacity:1;fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.21841836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
997
     d="m 76.280823,230.53494 c -1.611195,0 -2.908203,1.297 -2.908203,2.9082 v 0.23242 c 0,-0.87012 0.35019,-1.65487 0.917968,-2.22265 0.567779,-0.56778 1.354485,-0.91797 2.22461,-0.91797 z"
998
     id="path6106" />
999
  <path
1000
     inkscape:connector-curvature="0"
1001
     style="fill:#46c7f0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2950)"
1002
     d="m 76.515198,222.53494 c -0.870125,0 -1.656831,0.35019 -2.22461,0.91797 -0.567778,0.56778 -0.917968,1.35253 -0.917968,2.22265 v 29.71485 h 165.62109 v -29.71485 c 0,-0.87012 -0.35019,-1.65487 -0.91797,-2.22265 -0.56778,-0.56778 -1.35254,-0.91797 -2.22266,-0.91797 z"
1003
     id="path6104"
1004
     sodipodi:nodetypes="sssccssss" />
1005
  <path
1006
     sodipodi:nodetypes="ccssssc"
1007
     inkscape:connector-curvature="0"
1008
     style="fill:#e6e7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.218418;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter2950)"
1009
     d="M 238.99371,255.39041 H 73.37262 v 152.63392 c 0,1.6112 1.297008,2.90821 2.908203,2.90821 H 236.08551 c 1.6112,0 2.9082,-1.29701 2.9082,-2.90821 z"
1010
     id="path6100" />
1011
  <path
1012
     style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9509)"
1013
     d="m 240.99257,328.95043 65.23376,-1.01307"
1014
     id="path9485"
1015
     inkscape:connector-curvature="0"
1016
     sodipodi:nodetypes="cc" />
1017
  <path
1018
     sodipodi:nodetypes="cc"
1019
     inkscape:connector-curvature="0"
1020
     id="path9757"
1021
     d="m 481.61298,300.08996 65.23376,-1.01307"
1022
     style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9761)" />
1023
  <path
1024
     style="opacity:1;vector-effect:none;fill:#05556e;fill-opacity:1;stroke:#05556e;stroke-width:3.94158769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9767)"
1025
     d="M 552.61456,372.04139 487.3808,371.02832"
1026
     id="path9763"
1027
     inkscape:connector-curvature="0"
1028
     sodipodi:nodetypes="cc" />
1029
  <text
1030
     id="text2269"
1031
     y="62.149761"
1032
     x="115.43707"
1033
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1034
     xml:space="preserve"><tspan
1035
       y="62.149761"
1036
       x="115.43707"
1037
       id="tspan2267"
1038
       sodipodi:role="line">Text Edit</tspan></text>
1039
  <text
1040
     transform="rotate(-90)"
1041
     id="text2273"
1042
     y="43.507812"
1043
     x="-132.24059"
1044
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1045
     xml:space="preserve"><tspan
1046
       y="43.507812"
1047
       x="-132.24059"
1048
       id="tspan2271"
1049
       sodipodi:role="line">Today</tspan></text>
1050
  <text
1051
     id="text2277"
1052
     y="61.540386"
1053
     x="358.88168"
1054
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1055
     xml:space="preserve"><tspan
1056
       y="61.540386"
1057
       x="358.88168"
1058
       id="tspan2275"
1059
       sodipodi:role="line">Process</tspan></text>
1060
  <text
1061
     id="text2281"
1062
     y="59.34898"
1063
     x="605.30872"
1064
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1065
     xml:space="preserve"><tspan
1066
       y="59.34898"
1067
       x="605.30872"
1068
       id="tspan2279"
1069
       sodipodi:role="line">Output</tspan></text>
1070
  <text
1071
     id="text2285"
1072
     y="245.17946"
1073
     x="605.30872"
1074
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1075
     xml:space="preserve"><tspan
1076
       y="245.17946"
1077
       x="605.30872"
1078
       id="tspan2283"
1079
       sodipodi:role="line">Output</tspan></text>
1080
  <text
1081
     id="text2289"
1082
     y="247.37088"
1083
     x="358.88168"
1084
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1085
     xml:space="preserve"><tspan
1086
       y="247.37088"
1087
       x="358.88168"
1088
       id="tspan2287"
1089
       sodipodi:role="line">Process</tspan></text>
1090
  <text
1091
     id="text2293"
1092
     y="247.98026"
1093
     x="115.43707"
1094
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1095
     xml:space="preserve"><tspan
1096
       y="247.98026"
1097
       x="115.43707"
1098
       id="tspan2291"
1099
       sodipodi:role="line">Text Edit</tspan></text>
1100
  <text
1101
     transform="rotate(-90)"
1102
     id="text2297"
1103
     y="43.630859"
1104
     x="-363.15442"
1105
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1106
     xml:space="preserve"><tspan
1107
       y="43.630859"
1108
       x="-363.15442"
1109
       id="tspan2295"
1110
       sodipodi:role="line">Proposed</tspan></text>
1111
  <text
1112
     id="text2301"
1113
     y="314.01108"
1114
     x="98.034729"
1115
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none"
1116
     xml:space="preserve"><tspan
1117
       id="tspan2299"
1118
       sodipodi:role="line"
1119
       x="98.034729"
1120
       y="314.01108">R Markdown</tspan></text>
1121
  <text
1122
     id="text2305"
1123
     y="285.84311"
1124
     x="107.43903"
1125
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none"
1126
     xml:space="preserve"><tspan
1127
       id="tspan2303"
1128
       sodipodi:role="line"
1129
       x="107.43903"
1130
       y="285.84311">Markdown</tspan></text>
1131
  <text
1132
     id="text2309"
1133
     y="342.91147"
1134
     x="134.3277"
1135
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none"
1136
     xml:space="preserve"><tspan
1137
       id="tspan2307"
1138
       sodipodi:role="line"
1139
       x="134.3277"
1140
       y="342.91147">XML</tspan></text>
1141
  <text
1142
     id="text2313"
1143
     y="370.34702"
1144
     x="113.56207"
1145
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none"
1146
     xml:space="preserve"><tspan
1147
       id="tspan2311"
1148
       sodipodi:role="line"
1149
       x="113.56207"
1150
       y="370.34702">DocBook</tspan></text>
1151
  <text
1152
     id="text2317"
1153
     y="398.51498"
1154
     x="114.3526"
1155
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none"
1156
     xml:space="preserve"><tspan
1157
       id="tspan2315"
1158
       sodipodi:role="line"
1159
       x="114.3526"
1160
       y="398.51498">AsciiDoc</tspan></text>
1161
  <text
1162
     transform="rotate(-90)"
1163
     id="text2329"
1164
     y="43.507812"
1165
     x="-774.87335"
1166
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1167
     xml:space="preserve"><tspan
1168
       y="43.507812"
1169
       x="-774.87335"
1170
       id="tspan2327"
1171
       sodipodi:role="line">Example Processing Combination</tspan></text>
1172
  <text
1173
     id="text2333"
1174
     y="562.05426"
1175
     x="135.31207"
1176
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#f3fbfe;fill-opacity:1;stroke:none"
1177
     xml:space="preserve"><tspan
1178
       y="562.05426"
1179
       x="135.31207"
1180
       id="tspan2331"
1181
       sodipodi:role="line">XML</tspan></text>
1182
  <text
1183
     id="text2337"
1184
     y="495.6918"
1185
     x="381.64142"
1186
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:16.4059px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#333333;fill-opacity:0.866667;stroke:none"
1187
     xml:space="preserve"><tspan
1188
       y="495.6918"
1189
       x="381.64142"
1190
       id="tspan2335"
1191
       sodipodi:role="line">XSLT</tspan></text>
1192
  <text
1193
     id="text2341"
1194
     y="562.05426"
1195
     x="323.97742"
1196
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1197
     xml:space="preserve"><tspan
1198
       y="562.05426"
1199
       x="323.97742"
1200
       id="tspan2339"
1201
       sodipodi:role="line">XSLT Processor</tspan></text>
1202
  <text
1203
     id="text2345"
1204
     y="562.54059"
1205
     x="579.27557"
1206
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1207
     xml:space="preserve"><tspan
1208
       y="562.54059"
1209
       x="579.27557"
1210
       id="tspan2343"
1211
       sodipodi:role="line">R Markdown</tspan></text>
1212
  <text
1213
     id="text2349"
1214
     y="643.24084"
1215
     x="588.75018"
1216
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1217
     xml:space="preserve"><tspan
1218
       y="643.24084"
1219
       x="588.75018"
1220
       id="tspan2347"
1221
       sodipodi:role="line">Markdown</tspan></text>
1222
  <text
1223
     id="text2353"
1224
     y="642.63147"
1225
     x="339.61023"
1226
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1227
     xml:space="preserve"><tspan
1228
       y="642.63147"
1229
       x="339.61023"
1230
       id="tspan2351"
1231
       sodipodi:role="line">R Processor</tspan></text>
1232
  <text
1233
     id="text2357"
1234
     y="722.93903"
1235
     x="318.43912"
1236
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:21.3333px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1237
     xml:space="preserve"><tspan
1238
       y="722.93903"
1239
       x="318.43912"
1240
       id="tspan2355"
1241
       sodipodi:role="line">Variable Processor</tspan></text>
1242
  <text
1243
     id="text2361"
1244
     y="723.3316"
1245
     x="604.07831"
1246
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1247
     xml:space="preserve"><tspan
1248
       y="723.3316"
1249
       x="604.07831"
1250
       id="tspan2359"
1251
       sodipodi:role="line">HTML5</tspan></text>
1252
  <text
1253
     id="text2365"
1254
     y="630.84766"
1255
     x="81.211723"
1256
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:16.4059px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#333333;fill-opacity:0.866667;stroke:none"
1257
     xml:space="preserve"><tspan
1258
       y="630.84766"
1259
       x="81.211723"
1260
       id="tspan2363"
1261
       sodipodi:role="line">Structured Data Source</tspan></text>
1262
  <text
1263
     id="text2369"
1264
     y="756.39404"
1265
     x="215.65826"
1266
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:16.4059px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none"
1267
     xml:space="preserve"><tspan
1268
       y="756.39404"
1269
       x="215.65826"
1270
       id="tspan2367"
1271
       sodipodi:role="line">interpolated values</tspan></text>
1272
  <g
1273
     transform="translate(-0.25585322,11.831789)"
1274
     id="g2523">
1275
    <text
1276
       xml:space="preserve"
1277
       style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:16.4059px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1278
       x="156.49219"
1279
       y="708.2467"
1280
       id="text2373"><tspan
1281
         sodipodi:role="line"
1282
         id="tspan2371"
1283
         x="156.49219"
1284
         y="708.2467">CSON</tspan></text>
1285
    <text
1286
       xml:space="preserve"
1287
       style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:16.4059px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1288
       x="156.49219"
1289
       y="688.41504"
1290
       id="text2377"><tspan
1291
         sodipodi:role="line"
1292
         id="tspan2375"
1293
         x="156.49219"
1294
         y="688.41504">JSONNET</tspan></text>
1295
    <text
1296
       xml:space="preserve"
1297
       style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:16.4059px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1298
       x="156.49219"
1299
       y="668.24695"
1300
       id="text2381"><tspan
1301
         sodipodi:role="line"
1302
         id="tspan2379"
1303
         x="156.49219"
1304
         y="668.24695">JSON5</tspan></text>
1305
    <text
1306
       xml:space="preserve"
1307
       style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:16.4059px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1308
       x="156.49219"
1309
       y="648.07886"
1310
       id="text2385"><tspan
1311
         sodipodi:role="line"
1312
         id="tspan2383"
1313
         x="156.49219"
1314
         y="648.07886">JSON</tspan></text>
1315
    <text
1316
       xml:space="preserve"
1317
       style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:16.4059px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1318
       x="94.110725"
1319
       y="648.41534"
1320
       id="text2389"><tspan
1321
         sodipodi:role="line"
1322
         id="tspan2387"
1323
         x="94.110725"
1324
         y="648.41534">YAML</tspan></text>
1325
    <text
1326
       xml:space="preserve"
1327
       style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:16.4059px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1328
       x="94.110725"
1329
       y="668.24695"
1330
       id="text2393"><tspan
1331
         sodipodi:role="line"
1332
         id="tspan2391"
1333
         x="94.110725"
1334
         y="668.24695">TOML</tspan></text>
1335
    <text
1336
       xml:space="preserve"
1337
       style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:16.4059px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:0.933333;stroke:none"
1338
       x="94.110725"
1339
       y="688.41504"
1340
       id="text2397"><tspan
1341
         sodipodi:role="line"
1342
         id="tspan2395"
1343
         x="94.110725"
1344
         y="688.41504">XML</tspan></text>
1345
  </g>
1346
  <g
1347
     transform="translate(-1.2304677,-0.85937628)"
1348
     id="g2593">
1349
    <g
1350
       id="g2532">
1351
      <rect
1352
         id="rect4698"
1353
         ry="2.7292624"
1354
         y="91.740654"
1355
         x="129.16347"
1356
         height="32.205296"
1357
         width="54.039394"
1358
         style="fill:none;stroke:#05556e;stroke-width:2.72926;stroke-opacity:1" />
1359
      <path
1360
         style="fill:#05556e;fill-opacity:1;stroke-width:0.272926"
1361
         id="path4700"
1362
         d="M 135.98663,117.12279 V 98.56381 h 5.45852 l 5.45853,6.82315 5.45852,-6.82315 h 5.45853 v 18.55898 h -5.45853 v -10.64412 l -5.45852,6.82315 -5.45853,-6.82315 v 10.64412 z m 34.11578,0 -8.18779,-9.00657 h 5.45852 v -9.55241 h 5.45853 v 9.55241 h 5.45852 z"
1363
         inkscape:connector-curvature="0" />
1364
    </g>
1365
    <text
1366
       xml:space="preserve"
1367
       style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none"
1368
       x="108.73981"
1369
       y="152.80437"
1370
       id="text2407"><tspan
1371
         sodipodi:role="line"
1372
         id="tspan2405"
1373
         x="108.73981"
1374
         y="152.80437">Markdown</tspan></text>
1375
  </g>
1376
  <path
1377
     inkscape:connector-curvature="0"
1378
     d="m 417.86562,272.90923 c -2.81873,0.35302 -5.58858,1.78683 -7.90222,4.10047 -1.79226,1.78682 -3.43787,4.20365 -5.01832,7.35911 -1.28173,2.56347 -2.29191,5.21927 -2.90019,7.59265 l -0.1738,0.68975 -0.68975,0.35302 c -0.96673,0.49423 -1.81398,1.01561 -2.77528,1.69993 -3.29666,2.35709 -6.15341,5.19211 -8.53222,8.46705 -0.23354,0.32586 -0.45621,0.58656 -0.49966,0.58656 -0.038,0 -0.33673,-0.0435 -0.65716,-0.0923 -0.73863,-0.11949 -3.19891,-0.13578 -4.11676,-0.0272 -3.79633,0.46164 -7.25593,1.57502 -11.41613,3.68228 -3.00339,1.5207 -4.93685,2.87304 -6.8323,4.77391 -2.37881,2.37882 -3.80176,5.01832 -4.21452,7.82076 -0.0978,0.62457 -0.0978,2.39511 0,3.0414 0.51052,3.55193 2.55804,6.94636 5.27358,8.74404 3.15003,2.08554 7.40256,2.6558 12.27424,1.65105 3.62253,-0.75492 7.20161,-2.14527 10.77526,-4.19822 3.47046,-1.99321 5.87643,-4.18193 7.57093,-6.87575 0.27155,-0.43449 0.35845,-0.52682 0.53224,-0.59199 2.79701,-1.01018 4.74677,-2.05295 6.96265,-3.72572 2.02036,-1.5207 3.43244,-2.85675 6.0991,-5.77324 0.68432,-0.74949 0.8038,-0.91785 0.84182,-1.16225 0.0326,-0.17379 0.0543,-0.20095 0.15207,-0.17922 0.51595,0.10319 2.20502,0.11948 2.94908,0.0272 2.08553,-0.25526 4.05701,-1.10251 6.01763,-2.57976 2.61778,-1.97691 5.06177,-5.27901 6.78885,-9.17853 2.59606,-5.86556 3.57908,-10.80785 3.01425,-15.19073 -0.14121,-1.12423 -0.28241,-1.74881 -0.59742,-2.71554 -0.42905,-1.29803 -1.08621,-2.55804 -1.89001,-3.62796 -0.43449,-0.57026 -1.57502,-1.70536 -2.14528,-2.12898 -1.59131,-1.17855 -3.93753,-2.13442 -6.03936,-2.46028 -0.66259,-0.10319 -2.29735,-0.14664 -2.85132,-0.0815 z m 2.44399,7.82076 c 1.94433,0.46707 3.2152,2.04751 3.5302,4.39917 0.0815,0.58656 0.0815,2.10183 0,2.7427 -0.32043,2.62864 -1.26544,5.70263 -2.61235,8.48878 -1.01561,2.10725 -1.79226,3.34011 -2.88933,4.58383 -0.32587,0.36931 -1.38493,1.31975 -1.42838,1.2763 -0.005,-0.005 0.0706,-0.34216 0.1738,-0.74406 0.24983,-0.97759 0.34215,-1.56958 0.3856,-2.41683 0.0706,-1.58044 -0.27155,-3.09571 -0.98302,-4.30684 -1.20027,-2.05295 -3.17175,-3.41072 -5.47453,-3.78547 -0.11405,-0.0163 -0.20638,-0.0489 -0.20638,-0.076 0,-0.0217 0.19552,-0.53768 0.42905,-1.15139 1.41752,-3.67684 2.66666,-5.83298 4.30142,-7.40799 1.0482,-1.01562 1.70536,-1.40665 2.73726,-1.62933 0.51596,-0.11405 1.49355,-0.0978 2.03666,0.0272 z m -10.34078,17.93885 c 0.52139,0.54311 0.56483,0.76579 0.46164,2.25933 l -0.0326,0.51596 -0.14121,-0.21725 c -0.22811,-0.34215 -0.40733,-0.72233 -0.52682,-1.1188 -0.0652,-0.20095 -0.15207,-0.43992 -0.20095,-0.53224 -0.0706,-0.13035 -0.17922,-0.91243 -0.19008,-1.34691 0,-0.11949 0.29871,0.0923 0.63,0.43991 z m -7.36997,3.01425 c 0.3856,2.28649 1.18397,4.05159 2.44941,5.40393 l 0.45078,0.47793 -0.13577,0.14664 c -0.0706,0.0815 -0.46165,0.51052 -0.86355,0.9613 -1.55328,1.73795 -2.81873,2.98167 -4.05158,3.97012 -0.41819,0.34216 -0.78208,0.61915 -0.79837,0.61915 -0.0163,0 -0.0435,-0.0923 -0.0652,-0.20638 -0.076,-0.4019 -0.46708,-1.4664 -0.8038,-2.15614 -0.54311,-1.12424 -1.14596,-2.0095 -2.08554,-3.0577 l -0.45621,-0.50509 0.41276,-0.50509 c 1.19484,-1.47182 2.92192,-3.26951 4.43177,-4.62728 0.85811,-0.76578 1.37949,-1.21656 1.39578,-1.20027 0.005,0.005 0.0597,0.315 0.11949,0.67888 z m -16.52135,9.77052 c -0.0163,0.11405 -0.0815,0.54311 -0.14664,0.9613 -0.22267,1.47182 -0.23353,3.57365 -0.0272,4.78478 0.19008,1.10251 0.57569,2.11812 1.08078,2.81873 0.27699,0.38018 0.87441,0.97759 1.22199,1.20027 l 0.23354,0.1575 -0.15207,0.12492 c -0.60285,0.48879 -2.54174,1.58044 -4.18193,2.34622 -2.4114,1.12967 -4.36659,1.7651 -6.62049,2.16157 -0.77664,0.13578 -0.99932,0.15207 -2.09096,0.15207 -0.98846,0 -1.30889,-0.0217 -1.67278,-0.0978 -1.5207,-0.33672 -2.53088,-0.97216 -3.1989,-2.0095 -0.53225,-0.82552 -0.72234,-1.48268 -0.72777,-2.43855 0,-1.56415 0.57027,-2.68296 2.17244,-4.27969 1.78682,-1.77597 3.93753,-3.05227 7.72299,-4.5784 2.01493,-0.81467 4.20366,-1.37407 5.75151,-1.4664 0.74406,-0.0434 0.66803,-0.0652 0.63544,0.16294 z m 6.13712,3.5302 c -0.0163,0.0543 -0.0272,0.0109 -0.0272,-0.0923 0,-0.10319 0.0109,-0.14664 0.0272,-0.0978 0.0109,0.0543 0.0109,0.14121 0,0.19009 z"
1379
     id="path8164"
1380
     style="fill:#df4d65;fill-opacity:1;stroke:none;stroke-width:0.00543108" />
1381
  <g
1382
     transform="translate(1.378418e-5,1.0193503)"
1383
     id="g1168">
1384
    <text
1385
       id="text1158"
1386
       y="364.17905"
1387
       x="349.05551"
1388
       style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none"
1389
       xml:space="preserve"><tspan
1390
         id="tspan1156"
1391
         sodipodi:role="line"
1392
         x="349.05551"
1393
         y="364.17905">Processor</tspan></text>
1394
    <text
1395
       xml:space="preserve"
1396
       style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none"
1397
       x="370.40707"
1398
       y="392.17905"
1399
       id="text1162"><tspan
1400
         y="392.17905"
1401
         x="370.40707"
1402
         sodipodi:role="line"
1403
         id="tspan1160">Chain</tspan></text>
1404
  </g>
1405
  <g
1406
     transform="translate(0,-2.3144459)"
1407
     id="g1206">
1408
    <text
1409
       xml:space="preserve"
1410
       style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none"
1411
       x="586.44855"
1412
       y="327.56967"
1413
       id="text1190"><tspan
1414
         y="327.56967"
1415
         x="586.44855"
1416
         sodipodi:role="line"
1417
         id="tspan1188">Processor-</tspan></text>
1418
    <text
1419
       id="text1194"
1420
       y="355.56967"
1421
       x="588.43488"
1422
       style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:24px;line-height:1.25;font-family:'Roboto Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#05556e;fill-opacity:1;stroke:none"
1423
       xml:space="preserve"><tspan
1424
         id="tspan1192"
1425
         sodipodi:role="line"
1426
         x="588.43488"
1427
         y="355.56967">dependent</tspan></text>
1428
  </g>
1429
</svg>
11430
A docs/images/architecture/logos/html5.svg
1
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
2
	<title>HTML5 Logo</title>
3
	<path d="M108.4 0h23v22.8h21.2V0h23v69h-23V46h-21v23h-23.2M206 23h-20.3V0h63.7v23H229v46h-23M259.5 0h24.1l14.8 24.3L313.2 0h24.1v69h-23V34.8l-16.1 24.8l-16.1-24.8v34.2h-22.6M348.7 0h23v46.2h32.6V69h-55.6"/>
4
	<path fill="#e44d26" d="M107.6 471l-33-370.4h362.8l-33 370.2L255.7 512"/>
5
	<path fill="#f16529" d="M256 480.5V131H404.3L376 447"/>
6
	<path fill="#ebebeb" d="M142 176.3h114v45.4h-64.2l4.2 46.5h60v45.3H154.4M156.4 336.3H202l3.2 36.3 50.8 13.6v47.4l-93.2-26"/>
7
	<path fill="#fff" d="M369.6 176.3H255.8v45.4h109.6M361.3 268.2H255.8v45.4h56l-5.3 59-50.7 13.6v47.2l93-25.8"/>
8
</svg>
A docs/images/architecture/logos/links.svg
1
<?xml version="1.0" standalone="no"?>
2
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
3
 "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
4
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
5
 width="1280.000000pt" height="1123.000000pt" viewBox="0 0 1280.000000 1123.000000"
6
 preserveAspectRatio="xMidYMid meet">
7
<metadata>
8
Created by potrace 1.15, written by Peter Selinger 2001-2017
9
</metadata>
10
<g transform="translate(0.000000,1123.000000) scale(0.100000,-0.100000)"
11
fill="#000000" stroke="none">
12
<path d="M10280 11220 c-519 -65 -1029 -329 -1455 -755 -330 -329 -633 -774
13
-924 -1355 -236 -472 -422 -961 -534 -1398 l-32 -127 -127 -65 c-178 -91 -334
14
-187 -511 -313 -607 -434 -1133 -956 -1571 -1559 -43 -60 -84 -108 -92 -108
15
-7 0 -62 8 -121 17 -136 22 -589 25 -758 5 -699 -85 -1336 -290 -2102 -678
16
-553 -280 -909 -529 -1258 -879 -438 -438 -700 -924 -776 -1440 -18 -115 -18
17
-441 0 -560 94 -654 471 -1279 971 -1610 580 -384 1363 -489 2260 -304 667
18
139 1326 395 1984 773 639 367 1082 770 1394 1266 50 80 66 97 98 109 515 186
19
874 378 1282 686 372 280 632 526 1123 1063 126 138 148 169 155 214 6 32 10
20
37 28 33 95 -19 406 -22 543 -5 384 47 747 203 1108 475 482 364 932 972 1250
21
1690 478 1080 659 1990 555 2797 -26 207 -52 322 -110 500 -79 239 -200 471
22
-348 668 -80 105 -290 314 -395 392 -293 217 -725 393 -1112 453 -122 19 -423
23
27 -525 15z m450 -1440 c358 -86 592 -377 650 -810 15 -108 15 -387 0 -505
24
-59 -484 -233 -1050 -481 -1563 -187 -388 -330 -615 -532 -844 -60 -68 -255
25
-243 -263 -235 -1 1 13 63 32 137 46 180 63 289 71 445 13 291 -50 570 -181
26
793 -221 378 -584 628 -1008 697 -21 3 -38 9 -38 14 0 4 36 99 79 212 261 677
27
491 1074 792 1364 193 187 314 259 504 300 95 21 275 18 375 -5z m-1904 -3303
28
c96 -100 104 -141 85 -416 l-6 -95 -26 40 c-42 63 -75 133 -97 206 -12 37 -28
29
81 -37 98 -13 24 -33 168 -35 248 0 22 55 -17 116 -81z m-1357 -555 c71 -421
30
218 -746 451 -995 l83 -88 -25 -27 c-13 -15 -85 -94 -159 -177 -286 -320 -519
31
-549 -746 -731 -77 -63 -144 -114 -147 -114 -3 0 -8 17 -12 38 -14 74 -86 270
32
-148 397 -100 207 -211 370 -384 563 l-84 93 76 93 c220 271 538 602 816 852
33
158 141 254 224 257 221 1 -1 11 -58 22 -125z m-3042 -1799 c-3 -21 -15 -100
34
-27 -177 -41 -271 -43 -658 -5 -881 35 -203 106 -390 199 -519 51 -70 161
35
-180 225 -221 l43 -29 -28 -23 c-111 -90 -468 -291 -770 -432 -444 -208 -804
36
-325 -1219 -398 -143 -25 -184 -28 -385 -28 -182 0 -241 4 -308 18 -280 62
37
-466 179 -589 370 -98 152 -133 273 -134 449 0 288 105 494 400 788 329 327
38
725 562 1422 843 371 150 774 253 1059 270 137 8 123 12 117 -30z m1130 -650
39
c-3 -10 -5 -2 -5 17 0 19 2 27 5 18 2 -10 2 -26 0 -35z"/>
40
</g>
41
</svg>
142
A docs/images/architecture/logos/markdown.svg
1
1
<svg xmlns="http://www.w3.org/2000/svg" width="208" height="128" viewBox="0 0 208 128"><rect width="198" height="118" x="5" y="5" ry="10" stroke="#000" stroke-width="10" fill="none"/><path d="M30 98V30h20l20 25 20-25h20v68H90V59L70 84 50 59v39zm125 0l-30-33h20V30h20v35h20z"/></svg>
A docs/images/black-text.png
Binary file
A docs/images/blocked-text.png
Binary file
A docs/images/resolved-text.png
Binary file
A docs/images/screenshots/01.png
Binary file
A docs/images/screenshots/02.png
Binary file
A docs/images/screenshots/03.png
Binary file
A docs/images/screenshots/04.png
Binary file
A docs/images/screenshots/05.png
Binary file
A docs/images/screenshots/06.png
Binary file
A docs/images/screenshots/07.png
Binary file
A docs/images/screenshots/08.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
      "Licen[][yyyy] [name of copyright owner]
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:
19
10
* Redistributions of source code
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:
16
7
* Redistributions of source code
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
      "Licen[][yyyy] [name of copyright owner]
A docs/licenses/JAVA-IMAGE-SCALING.md
1
Java Image Scaling
2
3
Copyright (c) 2013, Morten Nobel-Joergensen
4
All rights reserved.
5
6
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
7
8
Redistributions of source code  in the
9
Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 
110
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
8
* in the
9
110
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 code2. in the
8
3. The name of the author may not be used to endorse or promote products
9
   derived from this software without specific prior written permission.
10
11
AUTHOR ``AS IS'' AND ANY EXPRESS OR
12
13
14
IN NO EVENT SHALL THE AUTHOR
15
INCIDENTAL,
16
NOT OF
17
118
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:
15
6
1. Redistributions of source code
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:
15
6
1. Redistributions of source code.
7
COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR   IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS     
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
8
 .
9
10
*
11
 
12
 
13
14
15
16
17
(
18
19
20
121
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
8
 .
9
10
*
11
 
12
 
13
14
15
16
17
18
19
20
21
122
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
      "Licen[][yyyy] [name of copyright owner]
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.
15
6
This license is cop
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.
12
3
This Font Software is licensed under the SIL Open Font License, Version 
4
 
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 cop 
6
 creation
7
 provide a free and
8
 improved in partnership
9
10
to  components as
11
 deleting,
12
 components of the
13
 the Font Software to a
14
 modify,
15
16
in  corresponding
17
 primary font name as
118
19
using 
A docs/logo/logo-original.svg
1
1
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
2
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1280" height="1024" viewBox="0 0 1280 1024" xml:space="preserve">
4
<desc>Created with Fabric.js 3.6.3</desc>
5
<defs>
6
</defs>
7
<g transform="matrix(1.9692780337941629 0 0 1.9692780337941629 640.0153846153846 512.012312418764)" id="background-logo"  >
8
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1;"  paint-order="stroke"  x="-325" y="-260" rx="0" ry="0" width="650" height="520" />
9
</g>
10
<g transform="matrix(1.9692780337941629 0 0 1.9692780337941629 640.0170725174504 420.4016715831266)" id="logo-logo"  >
11
<g style=""  paint-order="stroke"   >
12
		<g transform="matrix(2.537 0 0 -2.537 -86.35385711719567 85.244912)"  >
13
<linearGradient id="SVGID_1_302284" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-24.348526 -27.478867 -27.478867 24.348526 138.479 129.67187)"  x1="0" y1="0" x2="1" y2="0">
14
<stop offset="0%" style="stop-color:rgb(245,132,41);stop-opacity: 1"/>
15
<stop offset="100%" style="stop-color:rgb(251,173,23);stop-opacity: 1"/>
16
</linearGradient>
17
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: url(#SVGID_1_302284); fill-rule: nonzero; opacity: 1;"  paint-order="stroke"  transform=" translate(-127.92674550729492, -117.16399999999999)" d="m 118.951 124.648 c -9.395 -14.441 -5.243 -20.693 -5.243 -20.693 v 0 c 0 0 6.219 9.126 9.771 5.599 v 0 c 3.051 -3.023 -2.415 -8.668 -2.415 -8.668 v 0 c 0 0 33.24 13.698 17.995 28.872 v 0 c 0 0 -3.203 3.683 -7.932 3.684 v 0 c -3.46 0 -7.736 -1.97 -12.176 -8.794" stroke-linecap="round" />
18
</g>
19
		<g transform="matrix(2.537 0 0 -2.537 -84.52085711719567 70.2729119999999)"  >
20
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(250,220,153); fill-rule: nonzero; opacity: 1;"  paint-order="stroke"  transform=" translate(11.9895, -1.2609990716440347)" d="m 0 0 c 0 0 -6.501 6.719 -11.093 5.443 c -5.584 -1.545 -12.886 -12.078 -12.886 -12.078 c 0 0 5.98 16.932 15.29 15.731 C -1.19 8.127 0 0 0 0" stroke-linecap="round" />
21
</g>
22
		<g transform="matrix(2.537 0 0 -2.537 -22.327857117195663 48.729911999999956)"  >
23
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(201,158,82); fill-rule: nonzero; opacity: 1;"  paint-order="stroke"  transform=" translate(-4.189, -10.432)" d="m 0 0 l -0.87 16.89 l 3.995 3.974 l 6.123 -6.156 z" stroke-linecap="round" />
24
</g>
25
		<g transform="matrix(2.537 0 0 -2.537 -11.3118571171957 24.124911999999966)"  >
26
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(201,158,82); fill-rule: nonzero; opacity: 1;"  paint-order="stroke"  transform=" translate(4.0955, -2.037)" d="m 0 0 l -2.081 -2.069 l -6.11 6.143 l 2.081 2.069 z" stroke-linecap="round" />
27
</g>
28
		<g transform="matrix(2.537 0 0 -2.537 46.27614288280432 -57.96708800000005)"  >
29
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(217,170,93); fill-rule: nonzero; opacity: 1;"  paint-order="stroke"  transform=" translate(12.070999999999998, 9.599000000000004)" d="m 0 0 c -1.226 0.69 -2.81 0.523 -3.862 -0.524 c -1.275 -1.268 -1.28 -3.33 -0.013 -4.604 l -31.681 -31.501 l -6.11 6.143 c 19.224 19.305 25.369 35.582 25.369 35.582 c 15.857 2.364 27.851 8.624 33.821 12.335 z" stroke-linecap="round" />
30
</g>
31
		<g transform="matrix(2.537 0 0 -2.537 -26.842857117195706 8.501911999999976)"  >
32
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(217,170,93); fill-rule: nonzero; opacity: 1;"  paint-order="stroke"  transform=" translate(4.1075, -2.0525)" d="M 0 0 L -2.081 -2.069 L -8.215 4.11 L -6.141 6.174 Z" stroke-linecap="round" />
33
</g>
34
		<g transform="matrix(2.537 0 0 -2.537 -51.495857117195726 19.491911999999985)"  >
35
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(217,170,93); fill-rule: nonzero; opacity: 1;"  paint-order="stroke"  transform=" translate(10.434000000000001, -1.0939999999999994)" d="m 0 0 l -3.995 -3.974 l -16.873 0.96 l 14.752 9.176 z" stroke-linecap="round" />
36
</g>
37
		<g transform="matrix(2.537 0 0 -2.537 55.72014288280434 -48.441088000000036)"  >
38
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(201,158,82); fill-rule: nonzero; opacity: 1;"  paint-order="stroke"  transform=" translate(9.671499999999998, 11.999499999999998)" d="M 0 0 L 17.536 17.443 C 13.788 11.486 7.47 -0.468 5.021 -16.312 c 0 0 -15.526 -6.982 -35.765 -25.13 l -6.135 6.168 l 31.681 31.5 c 1.273 -1.28 3.33 -1.279 4.604 -0.012 C 0.435 -2.764 0.629 -1.223 0 0" stroke-linecap="round" />
39
</g>
40
</g>
41
</g>
42
<g transform="matrix(1.9692780337941629 0 0 1.9692780337941629 643.7363123827618 766.1975713477327)" id="text-logo-path"  >
43
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(247,149,33); fill-rule: nonzero; opacity: 1;"  paint-order="stroke"  transform=" translate(-186.83999999999997, 27.08)" d="M 4.47 -6.1 L 4.47 -6.1 L 4.47 -47.5 Q 4.47 -50.27 6.43 -52.23 Q 8.39 -54.19 11.16 -54.19 L 11.16 -54.19 Q 14.01 -54.19 15.95 -52.23 Q 17.89 -50.27 17.89 -47.5 L 17.89 -47.5 L 17.89 -30.09 L 34.95 -51.97 Q 35.74 -52.97 36.94 -53.58 Q 38.13 -54.19 39.42 -54.19 L 39.42 -54.19 Q 41.77 -54.19 43.42 -52.5 Q 45.07 -50.82 45.07 -48.5 L 45.07 -48.5 Q 45.07 -46.46 43.82 -44.93 L 43.82 -44.93 L 32.93 -31.44 L 46.8 -9.81 Q 47.84 -8.11 47.84 -6.27 L 47.84 -6.27 Q 47.84 -3.33 45.9 -1.39 Q 43.96 0.55 41.19 0.55 L 41.19 0.55 Q 39.42 0.55 37.89 -0.29 Q 36.37 -1.14 35.43 -2.57 L 35.43 -2.57 L 23.78 -21.15 L 17.89 -13.9 L 17.89 -6.1 Q 17.89 -3.33 15.93 -1.39 Q 13.97 0.55 11.16 0.55 L 11.16 0.55 Q 8.39 0.55 6.43 -1.39 Q 4.47 -3.33 4.47 -6.1 Z M 50.27 -19.24 L 50.27 -19.24 Q 50.27 -25.13 52.71 -29.78 Q 55.16 -34.43 59.7 -37.06 Q 64.24 -39.69 70.27 -39.69 L 70.27 -39.69 Q 76.37 -39.69 80.78 -37.09 Q 85.18 -34.49 87.43 -30.32 Q 89.69 -26.14 89.69 -21.6 L 89.69 -21.6 Q 89.69 -18.69 88.33 -17.26 Q 86.98 -15.84 83.86 -15.84 L 83.86 -15.84 L 62.89 -15.84 Q 63.23 -12.38 65.38 -10.31 Q 67.53 -8.25 70.86 -8.25 L 70.86 -8.25 Q 72.84 -8.25 74.19 -8.91 Q 75.54 -9.57 76.62 -10.64 L 76.62 -10.64 Q 77.62 -11.58 78.42 -12.03 Q 79.22 -12.48 80.43 -12.48 L 80.43 -12.48 Q 82.61 -12.48 84.19 -10.89 Q 85.77 -9.29 85.77 -7.04 L 85.77 -7.04 Q 85.77 -4.54 83.62 -2.77 L 83.62 -2.77 Q 81.71 -1.14 78.16 -0.03 Q 74.61 1.07 70.58 1.07 L 70.58 1.07 Q 64.76 1.07 60.13 -1.42 Q 55.5 -3.92 52.89 -8.53 Q 50.27 -13.14 50.27 -19.24 Z M 62.96 -23.57 L 62.96 -23.57 L 76.96 -23.57 Q 76.82 -26.97 74.93 -28.97 Q 73.05 -30.96 70.06 -30.96 L 70.06 -30.96 Q 67.08 -30.96 65.21 -28.97 Q 63.34 -26.97 62.96 -23.57 Z M 91.63 -19.24 L 91.63 -19.24 Q 91.63 -25.13 94.07 -29.78 Q 96.52 -34.43 101.06 -37.06 Q 105.6 -39.69 111.63 -39.69 L 111.63 -39.69 Q 117.73 -39.69 122.14 -37.09 Q 126.54 -34.49 128.79 -30.32 Q 131.04 -26.14 131.04 -21.6 L 131.04 -21.6 Q 131.04 -18.69 129.69 -17.26 Q 128.34 -15.84 125.22 -15.84 L 125.22 -15.84 L 104.25 -15.84 Q 104.59 -12.38 106.74 -10.31 Q 108.89 -8.25 112.22 -8.25 L 112.22 -8.25 Q 114.2 -8.25 115.55 -8.91 Q 116.9 -9.57 117.98 -10.64 L 117.98 -10.64 Q 118.98 -11.58 119.78 -12.03 Q 120.58 -12.48 121.79 -12.48 L 121.79 -12.48 Q 123.97 -12.48 125.55 -10.89 Q 127.13 -9.29 127.13 -7.04 L 127.13 -7.04 Q 127.13 -4.54 124.98 -2.77 L 124.98 -2.77 Q 123.07 -1.14 119.52 -0.03 Q 115.96 1.07 111.94 1.07 L 111.94 1.07 Q 106.12 1.07 101.49 -1.42 Q 96.86 -3.92 94.24 -8.53 Q 91.63 -13.14 91.63 -19.24 Z M 104.32 -23.57 L 104.32 -23.57 L 118.32 -23.57 Q 118.18 -26.97 116.29 -28.97 Q 114.4 -30.96 111.42 -30.96 L 111.42 -30.96 Q 108.44 -30.96 106.57 -28.97 Q 104.7 -26.97 104.32 -23.57 Z M 135.03 -6.03 L 135.03 -6.03 L 135.03 -33.14 Q 135.03 -35.64 136.85 -37.46 Q 138.67 -39.28 141.13 -39.28 L 141.13 -39.28 Q 143.7 -39.28 145.52 -37.46 Q 147.34 -35.64 147.34 -33.14 L 147.34 -33.14 L 147.34 -32.17 Q 148.97 -35.36 152.09 -37.42 Q 155.21 -39.49 159.82 -39.49 L 159.82 -39.49 Q 166.93 -39.49 170.19 -35.47 Q 173.44 -31.44 173.44 -24.44 L 173.44 -24.44 L 173.44 -6.03 Q 173.44 -3.33 171.5 -1.39 Q 169.56 0.55 166.86 0.55 L 166.86 0.55 Q 164.15 0.55 162.19 -1.39 Q 160.24 -3.33 160.24 -6.03 L 160.24 -6.03 L 160.24 -22.36 Q 160.24 -26.35 158.54 -27.91 Q 156.84 -29.47 154.65 -29.47 L 154.65 -29.47 Q 152.02 -29.47 150.13 -27.58 Q 148.24 -25.69 148.24 -20.73 L 148.24 -20.73 L 148.24 -6.03 Q 148.24 -3.33 146.3 -1.39 Q 144.36 0.55 141.65 0.55 L 141.65 0.55 Q 138.95 0.55 136.99 -1.39 Q 135.03 -3.33 135.03 -6.03 Z M 177.71 -47.56 L 177.71 -47.56 Q 177.71 -50.34 179.63 -52.26 Q 181.56 -54.19 184.23 -54.19 L 184.23 -54.19 Q 186.58 -54.19 188.39 -52.73 Q 190.19 -51.27 190.71 -48.99 L 190.71 -48.99 L 197.88 -15.12 L 206.52 -48.64 Q 207.07 -51.07 209.12 -52.63 Q 211.16 -54.19 213.69 -54.19 L 213.69 -54.19 Q 216.26 -54.19 218.25 -52.57 Q 220.25 -50.96 220.8 -48.64 L 220.8 -48.64 L 229.4 -15.39 L 236.64 -49.33 Q 237.06 -51.38 238.76 -52.78 Q 240.46 -54.19 242.61 -54.19 L 242.61 -54.19 Q 245.17 -54.19 246.94 -52.4 Q 248.71 -50.62 248.71 -48.05 L 248.71 -48.05 Q 248.71 -47.56 248.57 -46.73 L 248.57 -46.73 L 239.69 -7.38 Q 238.9 -3.99 236.11 -1.72 Q 233.32 0.55 229.68 0.55 L 229.68 0.55 Q 226.14 0.55 223.37 -1.61 Q 220.59 -3.78 219.73 -7.11 L 219.73 -7.11 L 213.07 -33.45 L 206.38 -7.11 Q 205.51 -3.71 202.79 -1.58 Q 200.07 0.55 196.53 0.55 L 196.53 0.55 Q 192.89 0.55 190.17 -1.72 Q 187.45 -3.99 186.65 -7.38 L 186.65 -7.38 L 177.85 -46.14 Q 177.71 -47.15 177.71 -47.56 Z M 253.35 -6.03 L 253.35 -6.03 L 253.35 -33.14 Q 253.35 -35.64 255.17 -37.46 Q 256.99 -39.28 259.46 -39.28 L 259.46 -39.28 Q 262.02 -39.28 263.84 -37.46 Q 265.66 -35.64 265.66 -33.14 L 265.66 -33.14 L 265.66 -31.44 L 265.94 -31.44 Q 266.8 -33.56 268.1 -35.24 Q 269.4 -36.92 270.69 -37.61 L 270.69 -37.61 Q 271.9 -38.24 273.46 -38.27 L 273.46 -38.27 Q 276.65 -38.27 278.14 -36.45 Q 279.63 -34.63 279.63 -32.52 L 279.63 -32.52 Q 279.63 -30.33 278.11 -28.62 Q 276.58 -26.9 274.08 -26.9 L 274.08 -26.9 Q 272.59 -26.9 271.07 -26.26 Q 269.54 -25.62 268.47 -24.34 L 268.47 -24.34 Q 266.56 -21.98 266.56 -17.68 L 266.56 -17.68 L 266.56 -6.03 Q 266.56 -3.33 264.62 -1.39 Q 262.68 0.55 259.98 0.55 L 259.98 0.55 Q 257.27 0.55 255.31 -1.39 Q 253.35 -3.33 253.35 -6.03 Z M 282.41 -49.71 L 282.41 -49.71 Q 282.41 -52 284.03 -53.61 Q 285.66 -55.23 287.95 -55.23 L 287.95 -55.23 L 291.21 -55.23 Q 293.5 -55.23 295.13 -53.6 Q 296.76 -51.97 296.76 -49.71 L 296.76 -49.71 Q 296.76 -47.43 295.11 -45.8 Q 293.46 -44.17 291.21 -44.17 L 291.21 -44.17 L 287.95 -44.17 Q 285.66 -44.17 284.03 -45.8 Q 282.41 -47.43 282.41 -49.71 Z M 282.96 -6.03 L 282.96 -6.03 L 282.96 -32.66 Q 282.96 -35.36 284.92 -37.32 Q 286.88 -39.28 289.58 -39.28 L 289.58 -39.28 Q 292.29 -39.28 294.23 -37.32 Q 296.17 -35.36 296.17 -32.66 L 296.17 -32.66 L 296.17 -6.03 Q 296.17 -3.33 294.21 -1.39 Q 292.25 0.55 289.58 0.55 L 289.58 0.55 Q 286.88 0.55 284.92 -1.39 Q 282.96 -3.33 282.96 -6.03 Z M 299.43 -34.29 L 299.43 -34.29 Q 299.43 -36.12 300.71 -37.41 Q 301.99 -38.69 303.76 -38.69 L 303.76 -38.69 L 306.19 -38.69 L 306.46 -43.96 Q 306.6 -46.32 308.34 -47.98 Q 310.07 -49.64 312.5 -49.64 L 312.5 -49.64 Q 314.99 -49.64 316.76 -47.86 Q 318.53 -46.07 318.53 -43.58 L 318.53 -43.58 L 318.53 -38.69 L 322.72 -38.69 Q 324.49 -38.69 325.77 -37.41 Q 327.06 -36.12 327.06 -34.36 L 327.06 -34.36 Q 327.06 -32.52 325.77 -31.24 Q 324.49 -29.95 322.72 -29.95 L 322.72 -29.95 L 318.81 -29.95 L 318.81 -14.14 Q 318.81 -11.23 320.05 -10.02 Q 321.3 -8.81 323.83 -8.81 L 323.83 -8.81 Q 325.46 -8.46 326.61 -7.14 Q 327.75 -5.82 327.75 -4.06 L 327.75 -4.06 Q 327.75 -2.57 326.94 -1.39 Q 326.12 -0.21 324.84 0.35 L 324.84 0.35 Q 322 0.83 318.11 0.87 L 318.11 0.87 Q 311.28 0.9 308.44 -2.5 L 308.44 -2.5 Q 305.67 -5.79 305.67 -12.65 L 305.67 -12.65 Q 305.67 -12.83 305.67 -13 L 305.67 -13 L 305.74 -29.95 L 303.76 -29.95 Q 301.99 -29.95 300.71 -31.24 Q 299.43 -32.52 299.43 -34.29 Z M 329.8 -19.24 L 329.8 -19.24 Q 329.8 -25.13 332.24 -29.78 Q 334.68 -34.43 339.23 -37.06 Q 343.77 -39.69 349.8 -39.69 L 349.8 -39.69 Q 355.9 -39.69 360.3 -37.09 Q 364.71 -34.49 366.96 -30.32 Q 369.21 -26.14 369.21 -21.6 L 369.21 -21.6 Q 369.21 -18.69 367.86 -17.26 Q 366.51 -15.84 363.39 -15.84 L 363.39 -15.84 L 342.42 -15.84 Q 342.76 -12.38 344.91 -10.31 Q 347.06 -8.25 350.39 -8.25 L 350.39 -8.25 Q 352.37 -8.25 353.72 -8.91 Q 355.07 -9.57 356.14 -10.64 L 356.14 -10.64 Q 357.15 -11.58 357.95 -12.03 Q 358.74 -12.48 359.96 -12.48 L 359.96 -12.48 Q 362.14 -12.48 363.72 -10.89 Q 365.3 -9.29 365.3 -7.04 L 365.3 -7.04 Q 365.3 -4.54 363.15 -2.77 L 363.15 -2.77 Q 361.24 -1.14 357.69 -0.03 Q 354.13 1.07 350.11 1.07 L 350.11 1.07 Q 344.29 1.07 339.66 -1.42 Q 335.03 -3.92 332.41 -8.53 Q 329.8 -13.14 329.8 -19.24 Z M 342.48 -23.57 L 342.48 -23.57 L 356.49 -23.57 Q 356.35 -26.97 354.46 -28.97 Q 352.57 -30.96 349.59 -30.96 L 349.59 -30.96 Q 346.61 -30.96 344.74 -28.97 Q 342.87 -26.97 342.48 -23.57 Z" stroke-linecap="round" />
44
</g>
45
</svg>
A docs/logo/logo-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:xlink="http://www.w3.org/1999/xlink"
9
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
10
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
11
   height="197.4767"
12
   viewBox="0 0 695.99768 197.4767"
13
   width="695.99768"
14
   version="1.1"
15
   id="svg37"
16
   sodipodi:docname="new-logo-text.svg"
17
   inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
18
  <metadata
19
     id="metadata43">
20
    <rdf:RDF>
21
      <cc:Work
22
         rdf:about="">
23
        <dc:format>image/svg+xml</dc:format>
24
        <dc:type
25
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
26
        <dc:title></dc:title>
27
      </cc:Work>
28
    </rdf:RDF>
29
  </metadata>
30
  <defs
31
     id="defs41">
32
    <linearGradient
33
       id="a"
34
       gradientTransform="matrix(-8.7796153,42.985832,-42.985832,-8.7796153,514.83476,136.06192)"
35
       gradientUnits="userSpaceOnUse"
36
       x1=".152358"
37
       x2=".968809"
38
       y1="-.044912"
39
       y2="-.049471">
40
      <stop
41
         offset="0"
42
         stop-color="#ec706a"
43
         id="stop2" />
44
      <stop
45
         offset="1"
46
         stop-color="#ecd980"
47
         id="stop4" />
48
    </linearGradient>
49
  </defs>
50
  <path
51
     style="fill:url(#a);fill-opacity:1.0;fill-rule:nonzero;stroke:none;stroke-width:1.226;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0"
52
     paint-order="stroke"
53
     d="m 496.76229,150.80474 c -4.25368,20.68081 3.28191,25.95476 3.28191,25.95476 v 0 c 0,0 3.00963,-13.19543 8.64082,-10.76172 v 0 c 4.83401,2.08299 1.12516,10.97002 1.12516,10.97002 v 0 c 0,0 31.78993,-30.5076 7.60484,-40.99434 v 0 c 0,0 -5.30287,-2.76791 -10.69842,-0.65209 v 0 c -3.94735,1.54891 -7.94375,5.71058 -9.95431,15.48337"
54
     stroke-linecap="round"
55
     id="path14" />
56
  <path
57
     d="m 530.80335,138.63592 -10.99206,-16.95952 1.75995,-6.49966 10.01483,2.71233 z"
58
     fill="#126d95"
59
     id="path9" />
60
  <path
61
     d="m 533.0598,112.36676 -0.91739,3.38458 -9.99361,-2.70665 0.91739,-3.38458 z"
62
     fill="#126d95"
63
     id="path11" />
64
  <g
65
     fill="#51a9cf"
66
     id="g19"
67
     transform="translate(-295.50101,-692.52836)">
68
    <path
69
       d="m 834.01973,741.0381 c -1.68105,0.0185 -3.22054,1.13771 -3.68367,2.84981 -0.56186,2.07405 0.665,4.21099 2.73743,4.77241 l -13.96475,51.52944 -9.99361,-2.70665 c 8.36013,-31.46487 4.99411,-51.98144 4.99411,-51.98144 14.99782,-11.92097 23.67,-25.56577 27.63101,-32.97331 z"
70
       id="path13" />
71
    <path
72
       d="m 818.56767,802.18881 -0.9174,3.38458 -10.03996,-2.72957 0.91314,-3.37522 z"
73
       id="path15" />
74
    <path
75
       d="m 817.07405,807.70594 -1.75995,6.49966 -18.03534,9.08805 9.78412,-18.31044 z"
76
       id="path17" />
77
  </g>
78
  <path
79
     d="m 540.69709,49.12083 7.72577,-28.52932 c -0.3195,8.40427 0.28451,24.55036 7.21678,42.41047 0,0 -11.89603,16.50235 -21.99788,47.3763 l -10.03442,-2.71758 13.96533,-51.5284 c 2.08221,0.56405 4.21039,-0.66603 4.77182,-2.73844 0.45427,-1.67248 -0.26571,-3.38317 -1.64739,-4.27302"
80
     fill="#126d95"
81
     id="path21" />
82
  <text
83
     transform="translate(-295.73751 -689.6407)"
84
     id="text25" />
85
  <g
86
     style="font-style:italic;font-weight:800;font-size:133.333;font-family:Merriweather Sans;letter-spacing:0;word-spacing:0;fill:#51a9cf"
87
     id="g35">
88
    <text
89
       x="16.133343"
90
       y="130.6234"
91
       id="text29"><tspan
92
         x="16.133343"
93
         y="130.6234"
94
         id="tspan27">KeenWr</tspan></text>
95
    <text
96
       x="552.53137"
97
       y="130.6234"
98
       id="text33"><tspan
99
         x="552.53137"
100
         y="130.6234"
101
         id="tspan31">te</tspan></text>
102
  </g>
103
</svg>
1104
A docs/logo/logo-text.zh-CN.svg
1
1
<svg height="197.4767" viewBox="0 0 493.25561 197.4767" width="493.25562" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientTransform="matrix(-8.7796153 42.985832 -42.985832 -8.7796153 810.33577 8312.52749 -472.07353)"/><text fill="#51a9cf" font-family="'Noto Serif CJK SC'" font-size="35.1025" letter-spacing="0" transform="matrix(3.7983969 0 0 3.7983969 -330.7653 961.00598)" word-spacing="0"><tspan x="91.011719" y="-209.05206"><tspan x="91.011719" y="-209.05206">智能写<tspan fill="#51a9cf"/></tspan></tspan><tspan x="91.011719" y="-165.17393"/></text><g transform="tran377.88503/svg>
A docs/logo/palette.txt
11
2
Blues
3
  Light - 51a9cf
4
  Dark - 126d95
5
6
Red & Yellow
7
  Light yellow - ecd980
8
  Light red - ec706a
9
  Dark red - 7e252f
10
11
Greens
12
  Light - 76A786
13
  Dark - 385742
14
15
Grayscale
16
  Light - bac2c5
17
  Dark - 394343
18
19
A docs/r.md
1
# Introduction
2
3
This document describes how to use the [R](https://www.r-project.org/)
4
programming language from within the application. The application uses an
5
interpreter known as [Renjin](https://www.renjin.org/) to integrate with R.
6
7
# Hello world
8
9
Complete the following steps to see R in action:
10
11
1. Start the application.
12
1. Click **File → New** to create a new file.
13
1. Click **File → Save As**.
14
1. Set **Name** to: `addition.Rmd`
15
1. Click **Save**.
16
17
Setting the file name extension tells the application what processor to
18
use when transforming the contents for display in the preview pane. Continue
19
by typing in the following text, including the backticks:
20
21
```r
22
`r#1 + 1`
23
```
24
25
The preview pane shows the result of `1` plus `1`:
26
27
```
28
2.0
29
```
30
31
# Bootstrap script
32
33
Being able to run R code while editing an R Markdown document is convenient.
34
Having the ability to call functions is where the power of R can be
35
leveraged.
36
37
Complete the following steps to call an R function from your own library:
38
39
1. Click **File → New** to create a new file.
40
1. Click **File → Save As**.
41
1. Browse to your home directory.
42
1. Set **Name** to: `library.R`.
43
1. Click **Save**.
44
1. Set the contents to:
45
    ``` r
46
    sum <- function( a, b ) {
47
      a + b
48
    }
49
    ```
50
1. Click the **Save** icon.
51
1. Click **R → Script**.
52
1. Set the **R Startup Script** contents to:
53
    ``` r
54
    source( 'library.R' );
55
    ```
56
1. Click **OK**.
57
1. Create a new file.
58
1. Set the contents to:
59
    ``` r
60
    `r#sum( 5, 5 )`
61
    ```
62
1. Save the file as `sum.R`.
63
64
The preview panel shows the result of calling the `sum` function:
65
66
```
67
10.0
68
```
69
70
This shows how the bootstrap script can load `library.R`, which defines
71
a `sum` function that is called by name in the Markdown document.
72
73
# Working directory
74
75
R files may be sourced from any directory, not just the user's home
76
directory. Accomplish this as follows:
77
78
1. Click **R → Directory**.
79
1. Set **Directory** to a different directory.
80
1. Click **OK**.
81
1. Create the directory if it does not exist.
82
1. Move `library.R` into the directory.
83
1. Append a new function to `library.R` as follows:
84
    ``` r
85
    mul <- function( a, b ) {
86
      a * b
87
    }
88
    ```
89
1. Click **R → Script**.
90
1. Set the **R Startup Script** contents to:
91
    ``` r
92
    setwd( '{{application.r.working.directory}}' );
93
    source( 'library.R' );
94
    ```
95
1. Change `sum.Rmd` to:
96
    ``` r
97
    `r#mul( 5, 5 )`
98
    ```
99
1. Close the file `sum.Rmd`.
100
1. Confirm saving the file when prompted.
101
1. Re-open `sum.Rmd`.
102
103
The preview panel shows:
104
105
```
106
25.0
107
```
108
109
Calling `setwd` using `'{{application.r.working.directory}}'` changes the
110
working directory where the R engine searches for source files.
111
112
# YAML variable definitions
113
114
To see how variable definitions work in R, try the following:
115
116
1. Create a new file.
117
1. Change the contents to (use spaces not tabs):
118
    ``` yaml
119
    project:
120
      title: Project Title
121
      author: Author Name
122
    ```
123
1. Save the file as `definitions.yaml`.
124
1. Click **File → Open**.
125
1. Set **Source Files** to **Variable Files**.
126
1. Select `definitions.yaml`.
127
1. Click **Open**.
128
1. Open `sum.Rmd` if it is not already open.
129
1. Type: `je`
130
1. Press `Ctrl+Space`
131
132
The editor inserts the following text (matches `je` against Pro**je**ct):
133
134
``` r
135
`r#x( v$project$title )`
136
```
137
138
The preview panel shows:
139
140
```
141
r#x( 'Project Title' )
142
```
143
144
This is because the application inserts variable reference names based
145
on the type of file being edited. By default, the R engine does not have
146
a function named `x` defined.
147
148
Continue as follows:
149
150
1. Click **R → Script**.
151
1. Append the following:
152
    ``` r
153
    x <- function( s ) {
154
      tryCatch( {
155
        r = eval( parse( text = s ) )
156
157
        ifelse( is.atomic( r ), r, s );
158
      },
159
      warning = function( w ) { s },
160
      error = function( e ) { s } )
161
    }
162
    ```
163
1. Click **OK**.
164
1. Close and re-open `sum.Rmd`.
165
166
The preview panel shows:
167
168
```
169
25.0
170
171
Project Title
172
```
173
174
The `x` function attempts to evaluate the expression defined by the YAML
175
variable. This means that the YAML variables can also include expressions
176
that R is capable of evaluating.
177
178
While the `x` function can be defined within the R Startup Script, it is
179
better practice to put it into its own library so that it can be reused
180
outside of the application.
181
1182
A docs/samples/korean.md
1
*Song of the Yellow Bird*:
2
3
	翩翩黃鳥,
4
	雌雄相依。
5
	念我之獨,
6
	誰其與歸?
7
8
English translation:
9
    	
10
	Orioles fly smoothly
11
	Female and male cuddle close together
12
	Thinking of my loneliness
13
	Whom shall I go with?
14
15
Fonts:
16
17
* Regular: 활판 인쇄술
18
* Bold: **활판 인쇄술**
19
* Monospace: `활판 인쇄술`
20
* Monospace bold: **`활판 인쇄술`**
21
* Math: $E=mc^2$
22
123
A docs/samples/math.yaml
1
---
2
formula:
3
  sqrt:
4
    value: "420"
5
  quadratic:
6
    a: "25"
7
    b: "84.906"
8
    c: "20"
19
A docs/samples/quadratic.Rmd
1
![Logo](../images/app-title)
2
3
Given the quadratic formula:
4
5
$x = \frac{-b \pm \sqrt{b^2 -4ac}}{2a}$
6
7
Formatted in an R Markdown document as follows:
8
9
    $x = \frac{-b \pm \sqrt{b^2 -4ac}}{2a}$
10
11
We can substitute the following values:
12
13
$a = `r# x(v$formula$quadratic$a)`, b = `r# x(v$formula$quadratic$b)`, c = `r# x(v$formula$quadratic$c)`$
14
15
`r# -x(v$formula$quadratic$b) + sqrt( v$formula$quadratic$b^2  - 4 * v$formula$quadratic$a * v$formula$quadratic$c )`
16
17
To arrive at two solutions:
18
19
$x = \frac{-b + \sqrt{b^2 -4ac}}{2a} = `r# (-x(v$formula$quadratic$b) + sqrt( x(v$formula$quadratic$b)^2  - 4 * x(v$formula$quadratic$a) * x(v$formula$quadratic$c) )) / (2 * x(v$formula$quadratic$a))`$
20
21
$x = \frac{-b - \sqrt{b^2 -4ac}}{2a} = `r# (-x(v$formula$quadratic$b) - sqrt( x(v$formula$quadratic$b)^2  - 4 * x(v$formula$quadratic$a) * x(v$formula$quadratic$c) )) / (2 * x(v$formula$quadratic$a))`$
22
23
Changing the variable values is reflected in the output immediately.
124
A docs/samples/tex.Rmd
1
# ![Logo](../images/app-title.png)
2
3
# Real-time equation rendering
4
5
Interpolated variables within R calculations, formatted as an equation:
6
7
$\sqrt{`r#x( v$formula$sqrt$value)`} = \pm `r# round(sqrt(x( v$formula$sqrt$value )),5)`$
8
9
# Maxwell's equations
10
11
$rot \vec{E} = \frac{1}{c} \frac{\partial{\vec{B}}}{\partial t}, div \vec{B} = 0$
12
13
$rot \vec{B} = \frac{1}{c} \frac{\partial{\vec{E}}}{\partial t} + \frac{4\pi}{c} \vec{j}, div \vec{E} = 4 \pi \rho_{\varepsilon}$
14
15
# Time-dependent Schrödinger equation
16
17
$- \frac{{\hbar ^2 }}{{2m}}\frac{{\partial ^2 \psi (x,t)}}{{\partial x^2 }} + U(x)\psi (x,t) = i\hbar \frac{{\partial \psi (x,t)}}{{\partial t}}$
18
19
# Discrete-time Fourier transforms
20
21
Unit step function: $u(n) \Leftrightarrow \frac{1}{1-e^{-jw}} + \sum_{k=-\infty}^{\infty} \pi \delta (\omega + 2\pi k)$
22
23
Shifted delta: $\delta (n - n_o ) \Leftrightarrow e^{ - j\omega n_o }$
24
25
# Faraday's Law
26
27
$\oint_C {E \cdot d\ell  =  - \frac{d}{{dt}}} \int_S {B_n dA}$
28
29
# Infinite series
30
31
$sin(x) = \sum_{n = 1}^{\infty}  {\frac{{( { - 1})^{n - 1} x^{2n - 1} }}{{( {2n - 1})!}}}$
32
33
# Magnetic flux
34
35
$\phi _m  = \int_S {N{{B}} \cdot {{\hat n}}dA = } \int_S {NB_n dA}$
36
37
# Driven oscillation amplitude
38
39
$A = \frac{{F_0 }}{{\sqrt {m^2 ( {\omega _0^2  - \omega ^2 } )^2  + b^2 \omega ^2 } }}$
40
41
# Optics
42
43
$\phi  = \frac{{2\pi }}{\lambda }a sin(\theta)$
144
A docs/screenshots.md
1
# Variables
2
3
Diagrams that include variables:
4
5
![GraphViz diagram screenshot](images/screenshots/01.png)
6
7
![Family tree diagram screenshot](images/screenshots/05.png)
8
9
# PDF themes
10
11
In the background of the following screenshot, the editor shows a novel
12
being edited:
13
14
![PDF themes](images/screenshots/08.png)
15
16
Highlighted items of note:
17
18
* PDF icon in the upper-left
19
* Novel metadata as integrated variables towards the top-left
20
* Theme selection dialog in the upper-middle
21
* Three different styles, including:
22
    * Boschet, based on Baskerville font, nicely styled
23
    * Handrit, based on Courier font, double-spaced, manuscript format
24
    * Tarmes, based on Times Roman font, minimal styling
25
* Variations in page numbers
26
* Manuscript includes word count, automatically
27
* Preferences dialog in the middle
28
29
# Internationalization
30
31
Poem with locale settings:
32
33
![Korean poem screenshot](images/screenshots/02.png)
34
35
# Equations
36
37
TeX equations with detached preview:
38
39
![TeX equations screenshot](images/screenshots/03.png)
40
41
# Dockable tabs
42
43
Document outline opened and docked in bottom-left corner:
44
45
![Document outline](images/screenshots/04.png)
46
147
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.
16
7
A skin is a set of styles, similar to cascading style sheet classes,
8
thaDaveJarvis/keenwrite/tree/masterDaveJarvis/keenwrite/blob/master1DaveJarvis/keenwrite
A docs/svg.md
1
# Introduction
2
3
The Scalable Vector Graphics (SVG) drawing software---[Batik](https://xmlgraphics.apache.org/batik/)---that's used by the application may be unable to read certain SVG files produced by [Inkscape](https://inkscape.org/). The result is that embedding the vector graphics files may trigger the following issues:
4
5
* Unable to create nested element
6
* Black blocks, no text displayed
7
* Black text instead of coloured
8
9
The remainder of this document explains these problems and how to fix them.
10
11
# Nested element
12
13
When referencing a vector graphic using Markdown, the status bar may show the following error:
14
15
> The current document is unable to create an element of the requested type (namespace: http://www.w3.org/2000/svg, name: flowRoot).
16
17
This error is due to a version mismatch of the `flowRoot` element that Inkscape creates.
18
19
## Fix
20
21
Resolve the issue by changing the SVG version number as follows:
22
23
1. Edit the vector graphics file using any text editor.
24
1. Find `version="1.1"` and change it to `version="1.2"`.
25
1. Save the file.
26
27
The SVG will now appear inside the application; however, the text may appear as black blocks.
28
29
# Black blocks
30
31
Depending on how text is added to a vector graphic in Inkscape, the text may be inserted within an element called a `flowRoot`. Although Batik recognizes `flowRoot` for SVG version 1.2, it cannot fully interpret the contents. Black blocks are drawn instead of the text, such as those depicted in the following figure:
32
33
![Missing text](images/blocked-text.png)
34
35
## Fix
36
37
Resolve the issue by "unflowing" all text elements as follows:
38
39
1. Start Inkscape.
40
1. Load the SVG file.
41
1. Select all the text elements.
42
1. Click **Text → Unflow**.
43
44
The text may change size and position; recreate the text without dragging using the text tool. After all the text areas have been recreated, continue as follows:
45
46
1. Click **Edit → XML Editor**.
47
1. Expand the **XML Editor** to see more elements.
48
1. Delete all elements named `svg:flowRoot`.
49
1. Save the file.
50
51
When the illustration is reloaded, the black blocks will have disappeared, but the text elements ignore any assigned colour.
52
53
# Black text
54
55
When an SVG `style` attribute contains a reference to `-inkscape-font-specification`, Batik ignores all values that follow said reference. This results in black text, such as:
56
57
![Black text](images/black-text.png)
58
59
## Fix
60
61
Resolve the issue of colourless text as follows:
62
63
1. Open the SVG file in a plain text editor.
64
1. Remove all references `-inkscape-font-specification:'<FONT>';`, including the trailing (or leading) semicolon.
65
1. Save the file.
66
67
When the illustration is reloaded, the colours will have reappeared, such as:
68
69
![Resolved text](images/resolved-text.png)
70
171
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
17
8
These are described in the subsequent sections. Once the requirements have been met, continue reading to learn how to typeset a hub.com/DaveJarvis/keenwrite/raw/master/scripts/localpath.bat">localpath.bat</a>huraw/main*What is ConTeXt?* ([English)
9
* ** ([English/raw/main/en/introCTX_eng.pdf) or [Spanish](https://raw.githubusercontent/main/es/introCTX_esp.pdf))
10
* ** ([English)
11
* *Typographic Programming* ([English
A docs/variables.md
1
# Introduction
2
3
This document describes how to use the application.
4
5
# Variable definitions
16
7
Variable definitions provide a way to insert key names having associated values into a document. The variable names and values are declared inside an external filbookending the key name within{{key}} 1
8
key_2: {{key}}{{novel.author}}Variable Files** to listVariable{{novel.author}}uble brace{{novel.title}}{{novel.title}}
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
A fonts/README.md
1
# Fonts
2
3
For best results, it is recommended that the Noto Font family is installed
4
on the system. The required font families include:
15
6
* Sans-serif --- editor pane
7
* Serif --- preview pane
8
* Serif monospace --- prevnt familie
A fonts/noto-hk.zip
Binary file
A fonts/noto-jp.zip
Binary file
A fonts/noto-kr.zip
Binary file
A fonts/noto-sc.zip
Binary file
A fonts/noto-tc.zip
Binary file
A gradle.properties
1
org.gradle.jvmargs=-Xmx1G -XX:MaxPermSize=512m
2
org.gradle.daemon=true
3
org.gradle.parallel=true
4
15
A images/broken-camera.svg
1
<svg height='19pt' viewBox='0 0 25 19' width='25pt' xmlns='http://www.w3.org/2000/svg'><g fill='#454545'><path d='m8.042969 11.085938c.332031 1.445312 1.660156 2.503906 3.214843 2.558593zm0 0'/><path d='m6.792969 9.621094-.300781.226562.242187.195313c.015625-.144531.03125-.28125.058594-.421875zm0 0'/><path d='m10.597656.949219-2.511718.207031c-.777344.066406-1.429688.582031-1.636719 1.292969l-.367188 1.253906-3.414062.28125c-1.027344.085937-1.792969.949219-1.699219 1.925781l.976562 10.621094c.089844.976562.996094 1.699219 2.023438 1.613281l11.710938-.972656-3.117188-2.484375c-.246094.0625-.5.109375-.765625.132812-2.566406.210938-4.835937-1.597656-5.0625-4.039062-.023437-.25-.019531-.496094 0-.738281l-.242187-.195313.300781-.226562c.359375-1.929688 2.039062-3.472656 4.191406-3.652344.207031-.015625.414063-.015625.617187-.007812l.933594-.707032zm0 0'/><path d='m10.234375 11.070312 2.964844 2.820313c.144531.015625.285156.027344.433593.027344 1.890626 0 3.429688-1.460938 3.429688-3.257813 0-1.792968-1.539062-3.257812-3.429688-3.257812-1.890624 0-3.429687 1.464844-3.429687 3.257812 0 .140625.011719.277344.03125.410156zm0 0'/><path d='m14.488281.808594 1.117188 4.554687-1.042969.546875c2.25.476563 3.84375 2.472656 3.636719 4.714844-.199219 2.191406-2.050781 3.871094-4.285157 4.039062l2.609376 2.957032 4.4375.371094c1.03125.085937 1.9375-.640626 2.027343-1.617188l.976563-10.617188c.089844-.980468-.667969-1.839843-1.699219-1.925781l-3.414063-.285156-.371093-1.253906c-.207031-.710938-.859375-1.226563-1.636719-1.289063zm0 0'/></g></svg>
12
A images/logo64.png
Binary file
A installer.sh
1
#!/usr/bin/env bash
12
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 6.0.1"
8
ARG_JAVA_UPDATE="9
A keenwrite.sh
1
#!/usr/bin/env bash
2
3
java --illegal-access=permit -jar build/libs/keenwrite.jar 2> /dev/null
4
15
A libs/jmathtex.jar
Binary file
A libs/jsymspell/jsymspell-core-1.0.jar
Binary file
A libs/tiwulfx-dock-0.1.jar
Binary file
A libs/tokenize.jar
Binary file
A release.sh
1
#!/usr/bin/env bash
12
3
# ---------------------------------------------------------------------------
4
# This script builds Windows, Linux, and Java archive binaries for a
5
# release.
6
# --------------------------------------------------------------------------
A scripts/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
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
A settings.gradle
11
A src/main/java/com/keenwrite/AbstractFileFactory.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite;
3
4
import com.keenwrite.io.FileType;
5
6
import java.nio.file.Path;
7
8
import static com.keenwrite.constants.Constants.GLOB_PREFIX_FILE;
9
import static com.keenwrite.constants.Constants.sSettings;
10
import static com.keenwrite.io.FileType.UNKNOWN;
11
import static com.keenwrite.predicates.PredicateFactory.createFileTypePredicate;
12
13
/**
14
 * Provides common behaviours for factories that instantiate classes based on
15
 * file type.
16
 */
17
public abstract class AbstractFileFactory {
18
19
  /**
20
   * Determines the file type from the path extension. This should only be
21
   * called when it is known that the file type won't be a definition file
22
   * (e.g., YAML or other definition source), but rather an editable file
23
   * (e.g., Markdown, XML, etc.).
24
   *
25
   * @param path The path with a file name extension.
26
   * @return The FileType for the given path.
27
   */
28
  public static FileType lookup( final Path path ) {
29
    assert path != null;
30
31
    return lookup( path, GLOB_PREFIX_FILE );
32
  }
33
34
  /**
35
   * Creates a file type that corresponds to the given path.
36
   *
37
   * @param path   Reference to a variable definition file.
38
   * @param prefix One of GLOB_PREFIX_DEFINITION or GLOB_PREFIX_FILE.
39
   * @return The file type that corresponds to the given path.
40
   */
41
  protected static FileType lookup( final Path path, final String prefix ) {
42
    assert path != null;
43
    assert prefix != null;
44
45
    final var keys = sSettings.getKeys( prefix );
46
47
    var found = false;
48
    var fileType = UNKNOWN;
49
50
    while( keys.hasNext() && !found ) {
51
      final var key = keys.next();
52
      final var patterns = sSettings.getStringSettingList( key );
53
      final var predicate = createFileTypePredicate( patterns );
54
55
      if( found = predicate.test( path.toFile() ) ) {
56
        // Remove the EXTENSIONS_PREFIX to get the file name extension mapped
57
        // to a standard name (as defined in the settings.properties file).
58
        final String suffix = key.replace( prefix + '.', "" );
59
        fileType = FileType.from( suffix );
60
      }
61
    }
62
63
    return fileType;
64
  }
65
}
166
A src/main/java/com/keenwrite/Bootstrap.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite;
3
4
import com.keenwrite.constants.Constants;
5
6
import java.io.InputStream;
7
import java.org.apache.batik.util.ParsedURL.setGlobalUserAgentof-/**
8
   * Order matters, this m.
9
   */Properties static { ) ) {
10
      P.load( inignored ) {
11
      // Bootstrap properties cannot be found, throw in the towel.
12
    }
13
  }
14
 =  = Launcher.getVersion()YEAR = getYear();
115
16
  static { );
17
    setGlobalUserAgent( System.g ) );
A src/main/java/com/keenwrite/Caret.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwriteconstants The
3
 *llows observers to be notified when the value of the caret changes.
4
   *
5
   * @return An observer for the caret's document offset.
6
   */
7
  publictextOffsetProperty <p>
8
   * If the {@link Caret} has not been properly built, this will return a
9
   * string for the status bar having all values set to zero. This can happen
10
   * during unit testing, but should not happen any other time.
11
   * </p>try {
12
   + 1,
13
  + 1 );
14
    } catch( final Exception ex ) {
15
   0, 0, 0 );
16
    }
17
  }
18
}
119
A src/main/java/com/keenwrite/DefinitionNameInjector.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite;
3
editors.TextDefinitioneditors.TextEditoreditorsconstantsevents.StatusEvent.cluePrevent instantia() {
4
  }
5
6
  /**
7
   * F
8
   * reference.
9
   */
10
  public static void autoinsert(
11
    final TextEditor editor,
12
    final TextDefinition definitions,
13
    final SigilOperator operator ) {
14
    try {
15
      if( definitions.isEmptyvar indexes = editor.getCaretWord();
16
        final var word = editor.getText( indexesdefinitions,final var entokened = operator.entoken          editor.replaceText( indexes, operator.apply( entokened ) );
17
            definitions.ex, ex );
18
    }Match the word by: exact, beginning, containment, or other "ConstantConditions" )
19
  private static
20
    final TextDefinition definition,definitiondefinitiondefinitiondefinition}
121
A src/main/java/com/keenwrite/ExportFormat.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite;
3
4
import java.io.File;
5
import java.nio.file.Path;
6
7
import static org.apache.commons.io.FilenameUtils.removeExtension;
8
9
/**
10
 * Provides controls for processor behaviour when transforming input documents.
11
 */
12
public enum ExportFormat {
13
14
  /**
15
   * For HTML exports, encode TeX as SVG. Treat image links relatively.
16
   */
17
  HTML_TEX_SVG( ".html" ),
18
19
  /**
20
   * For HTML exports, encode TeX using {@code $} delimiters, suitable for
21
   * rendering by an external TeX typesetting engine (or online with KaTeX).
22
   * Treat image links relatively.
23
   */
24
  HTML_TEX_DELIMITED( ".html" ),
25
26
  /**
27
   * For XHTML exports, encode TeX using {@code $} delimiters.
28
   */
29
  XHTML_TEX( ".xml" ),
30
31
  /**
32
   * Indicates that the processors should export to a Markdown format.
33
   * Treat image links relatively.
34
   */
35
  MARKDOWN_PLAIN( ".out.md" ),
36
37
  /**
38
   * Exports as PDF file format.
39
   */
40
  APPLICATION_PDF( ".pdf" ),
41
42
  /**
43
   * Indicates no special export format is to be created. No extension is
44
   * applicable. Image links must use absolute directories.
45
   */
46
  NONE( "" );
47
48
  /**
49
   * Preferred file name extension for the given file type.
50
   */
51
  private final String mExtension;
52
53
  ExportFormat( final String extension ) {
54
    mExtension = extension;
55
  }
56
57
  /**
58
   * Returns the given {@link File} with its extension replaced by one that
59
   * matches this {@link ExportFormat} extension.
60
   *
61
   * @param file The file to perform an extension swap.
62
   * @return The given file with its extension replaced.
63
   */
64
  public File toExportFilename( final File file ) {
65
    return new File( removeExtension( file.getName() ) + mExtension );
66
  }
67
68
  /**
69
   * Delegates to {@link #toExportFilename(File)} after converting the given
70
   * {@link Path} to an instance of {@link File}.
71
   *
72
   * @param path The {@link Path} to convert to a {@link File}.
73
   * @return The given path with its extension replaced.
74
   */
75
  public File toExportFilename( final Path path ) {
76
    return toExportFilename( path.toFile() );
77
  }
78
}
179
A src/main/java/com/keenwrite/Launcher.java
1
/* Copyright 2020-2021 -- All rights reserved. */
2
package com.keenwritecom.keenwrite.Bootstrap.*;
3
import static com.keenwrite.PermissiveCertificate.installTrustManager;Appfinal{
4
    try {
5
      installTrustManager();
6
    MainApp.main( args );
7
    } catch( final Throwable t ) {
8
      log( t );
9
    }
10
  }
11
12
  @SuppressWarnings( "RedundantStringFormatCall" APP_TITLE, APP_VERSION2016-%sAPP_YEAR15-/**
13
   * Returns the application version number retrieved from the application
14
   * properties file. The properties file is generated at build time, which
15
   * keys off the repository.
16
   *
17
   * @return The application version number.
18
   * @throws RuntimeException An {@link IOException} occurred.
19
   */
20
  public{
21
    try {
22
      final var  } catch( final Exception ex ) {
23
      throw new RuntimeException( ex );
24
    }
25
  }
26
27
  @SuppressWarnings( "SameParameterValue" var
28
  /**
29
   * Logs the message of an error to the console.
30
   *
31
   * @param error The fatal error that could not be handled.
32
   */log( final Throwable error ) {
33
    var message = error.getMessage();
34
35
    if( message != null && message.toLowerCase().contains( "javafx" ) ) {
36
      message = "Re-run using a Java Runtime Environment that includes JavaFX.";
37
    }
38
39
    out( format( "ERROR: %s", message ) );
40
  }
41
}
142
A src/main/java/com/keenwrite/MainApp.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite;
13
4
import com.keenwrite.events.HyperlinkOpenEvent;
5
import com.keenwrite.preferences.Workspace;
6
import javafx.application.Application;
7
import javafx.event.Eve
8
    // because it interacts with GUI properties
A src/main/java/com/keenwrite/MainPane.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite;
3
4
import com.keenwrite.TextDefinition;
5
import com.keenwrite.editors.TextEditor;
6
import com.keenwrite.editomWorkspace.save();
17
8
}
9
    } )
A src/main/java/com/keenwrite/MainScene.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite;
13
4
import com.keenwrite.io.FileModifiedListener;
5
import com.keenwrite.io.FileWatchService;
6
import com.keenwrite.preferences.Workspace;
7
import com.keenwrite.uconstantsSkinSKINSKINskinProperty( KEY_UI_SKINSKIN_CUSTOM );
8
    final var inSkinSkinSkin, exSkinSkinSkinSkinSKIN
A src/main/java/com/keenwrite/Messages.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite;
3
4
import com.keenwrite.preferences.KeyEnumerationimport static com.keenwrite.constants.Constants.APP_BUNDLE_NAME;
5
import static java.util.ResourceBundle.getBundle;
6
7
/**
8
 * Recu to other
9
 */
10
public final
11
    getBundle( APP_   @SuppressWarnings( "SameParameterValue" )final ResourceBundle props, final String s ) {
12
    final var len = s.length();
13
    final var stack = new Stack<StringBuilder>();
14
    vavar open = false;
15
16
    for( varfinal v
17
            if( stack.size() > 20 ) {
18
              final var m = get( "Main.status.error.messages.recursion", s );
19
          m );
20
            }
21
  open = true;
22
          }
23
open ) {
24
            open = false;
25
            final varopen ) {
26
      final var m = get( "Main.status.error.messages.syntax", s );
27
mfinal String key ) {
28
    try {
29
    } catch( final Exception ignored ) {
30
      return key;
31
    }final Key key ) {
32
    return get( key.toString() );
33
  }
34
Literal( final String key ) {
35
    return;
36
  }
37
final String key, final boolean interpolate ) {
38
    return interpolate ? get( key ) : getLiteral( key   holders.final String key, final
39
  /**
40
   * Answers whether the given key is contained in the application's messages
41
   * properties file.
42
   *
43
   * @param key The key to look for in the {@link ResourceBundle}.
44
   * @return {@code true} when the key exists as an exact match.
45
   */
46
  puboolean containsKey( final String key ) {
47
    return RESOURCE_BUNDLE.containsKey( key all key names in the application's messages properties file.
48
   *
49
   * @return All key names in the {@link ResourceBundle} encapsulated by
50
   * this classEnumeration<String> getKeys() {
51
    return RESOURCE_BUNDLE.getKeys();
52
  }
53
}
154
A src/main/java/com/keenwrite/PermissiveCertificate.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite;
3
4
import javax.net.ssl.*;
5
import java.security.SecureRandom;
6
import java.security.cert.X509Certificate;
7
8
import static javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier;
9
import static javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory;
10
11
/**
12
 * Responsible for trusting all certificate chains. The purpose of this class
13
 * is to work-around certificate issues caused by software that blocks
14
 * HTTP requests. For example, zscaler may block HTTP requests to kroki.io
15
 * when generating diagrams.
16
 */
17
public final class PermissiveCertificate {
18
  /**
19
   * Create a trust manager that does not validate certificate chains.
20
   */
21
  private final static TrustManager[] TRUST_ALL_CERTS = new TrustManager[]{
22
    new X509TrustManager() {
23
      @Override
24
      public X509Certificate[] getAcceptedIssuers() {
25
        return new X509Certificate[ 0 ];
26
      }
27
28
      @Override
29
      public void checkClientTrusted(
30
        X509Certificate[] certs, String authType ) {
31
      }
32
33
      @Override
34
      public void checkServerTrusted(
35
        X509Certificate[] certs, String authType ) {
36
      }
37
    }
38
  };
39
40
  /**
41
   * Responsible for permitting all hostnames for making HTTP requests.
42
   */
43
  private static class PermissiveHostNameVerifier implements HostnameVerifier {
44
    @Override
45
    public boolean verify( final String hostname, final SSLSession session ) {
46
      return true;
47
    }
48
  }
49
50
  /**
51
   * Use {@link #installTrustManager()}.
52
   */
53
  private PermissiveCertificate() {
54
  }
55
56
  /**
57
   * Install the all-trusting trust manager. If this fails it means that in
58
   * certain situations the HTML preview may fail to render diagrams. A way
59
   * to work-around the issue is to install a local server for generating
60
   * diagrams.
61
   */
62
  public static boolean installTrustManager() {
63
    try {
64
      final var context = SSLContext.getInstance( "SSL" );
65
      context.init( null, TRUST_ALL_CERTS, new SecureRandom() );
66
      setDefaultSSLSocketFactory( context.getSocketFactory() );
67
      setDefaultHostnameVerifier( new PermissiveHostNameVerifier() );
68
      return true;
69
    } catch( final Exception ex ) {
70
      return false;
71
    }
72
  }
73
}
174
A src/main/java/com/keenwrite/ScrollEventHandler.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite;
13
4
import com.keenwrite.events.ScrollLockEventimport static javax.swing.SwingUtilities.invokeLaternvokeLater( () -> {
5
      if( isEnabled() ) {
6
        // e is for editor pane
7
    // p is for preview pane
8
    }
9
    } );
A src/main/java/com/keenwrite/Services.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite;
3
4
import java.util.HashMap;
5
import java.util.Map;
6
import java.util.ServiceLoader;
17
8
/**
9
 * Responsible for loading services. The services are treated as singleton
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;
17
8
import jav
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
A src/main/java/com/keenwrite/editors/TextDefinition.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.editors;
3
4
import com.keenwrite.editors.definition.DefinitionEditor;
5
import com.keenwrite.editors.definition.DefinitionTreeItem;
6
import com.keenwrite.editors.markdown.MarkdownEditor;
7
import com.keenwrite.sigils.Tokens;
8
import javafx.scene.control.TreeItem;
9
10
import java.util.Map;
11
12
/**
13
 * Differentiates an instance of {@link TextResource} from an instance of
14
 * {@link DefinitionEditor} or {@link MarkdownEditor}.
15
 */
16
public interface TextDefinition extends TextResource {
17
  /**
18
   * Converts the definitions into a map, ready for interpolation.
19
   *
20
   * @return The list of key value pairs delimited with tokens.
21
   */
22
  Map<String, String> toMap();
23
24
  /**
25
   * Performs string interpolation on the values in the given map. This will
26
   * change any value in the map that contains a variable that matches
27
   * the definition regex pattern against the given {@link Tokens}.
28
   *
29
   * @param map Contains values that represent references to keys.
30
   * @param tokens The beginning and ending tokens that delimit variables.
31
   */
32
  Map<String, String> interpolate( Map<String, String> map, Tokens tokens );
33
34
  /**
35
   * Requests that the visual representation be expanded to the given
36
   * node.
37
   *
38
   * @param node Request expansion to this node.
39
   */
40
  <T> void expand( TreeItem<T> node );
41
42
  /**
43
   * Adds a new item to the definition hierarchy.
44
   */
45
  void createDefinition();
46
47
  /**
48
   * Edits the currently selected definition in the hierarchy.
49
   */
50
  void renameDefinition();
51
52
  /**
53
   * Removes the currently selected definition in the hierarchy.
54
   */
55
  void deleteDefinitions();
56
57
  /**
58
   * Finds the definition that exact matches the given text.
59
   *
60
   * @param text The value to find, never {@code null}.
61
   * @return The leaf that contains the given value.
62
   */
63
  DefinitionTreeItem<String> findLeafExact( String text );
64
65
  /**
66
   * Finds the definition that starts with the given text.
67
   *
68
   * @param text The value to find, never {@code null}.
69
   * @return The leaf that starts with the given value.
70
   */
71
  DefinitionTreeItem<String> findLeafStartsWith( String text );
72
73
  /**
74
   * Finds the definition that contains the given text, matching case.
75
   *
76
   * @param text The value to find, never {@code null}.
77
   * @return The leaf that contains the exact given value.
78
   */
79
  DefinitionTreeItem<String> findLeafContains( String text );
80
81
  /**
82
   * Finds the definition that contains the given text, ignoring case.
83
   *
84
   * @param text The value to find, never {@code null}.
85
   * @return The leaf that contains the given value, regardless of case.
86
   */
87
  DefinitionTreeItem<String> findLeafContainsNoCase( String text );
88
89
  /**
90
   * Answers whether there are any definitions written.
91
   *
92
   * @return {@code true} when there are no definitions.
93
   */
94
  boolean isEmpty();
95
}
196
A src/main/java/com/keenwrite/editors/TextEditor.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.editors;
3
4
import com.keenwrite.Caret;
5
import javafx.scene.control.IndexRange;
6
import org.fxmisc.flowless.VirtualizedScrollPane;
7
import org.fxmisc.richtext.StyleClassedTextArea;
8
9
/**
10
 * Responsible for differentiating an instance of {@link TextResource} from
11
 * other {@link TextResource} subtypes, such as a {@link TextDefinition}.
12
 * This is primarily used as a marker interface, but also defines a minimal
13
 * set of functionality required by all {@link TextEditor} instances, which
14
 * includes scrolling facilities.
15
 */
16
public interface TextEditor extends TextResource {
17
18
  /**
19
   * Returns the scrollbars associated with the editor's view so that they
20
   * can be moved for synchronized scrolling.
21
   *
22
   * @return The initialized horizontal and vertical scrollbars.
23
   */
24
  VirtualizedScrollPane<StyleClassedTextArea> getScrollPane();
25
26
  StyleClassedTextArea getTextArea();
27
28
  /**
29
   * Requests that styling be added to the document between the given
30
   * integer values.
31
   *
32
   * @param indexes Document offset where style is to start and end.
33
   * @param style   The style class to apply between the given offset indexes.
34
   */
35
  default void stylize( final IndexRange indexes, final String style ) {
36
  }
37
38
  /**
39
   * Requests that the most recent styling for the given style class be
40
   * removed from the document between the given integer values.
41
   */
42
  default void unstylize( final String style ) {
43
  }
44
45
  /**
46
   * Returns the complete text for the specified paragraph index.
47
   *
48
   * @param paragraph The zero-based paragraph index.
49
   * @throws IndexOutOfBoundsException The paragraph index is less than zero
50
   *                                   or greater than the number of
51
   *                                   paragraphs in the document.
52
   */
53
  String getText( int paragraph ) throws IndexOutOfBoundsException;
54
55
  /**
56
   * Returns the text between the indexes specified by the given
57
   * {@link IndexRange}.
58
   *
59
   * @param indexes The start and end document indexes to reference.
60
   * @return The text between the specified indexes.
61
   * @throws IndexOutOfBoundsException The indexes are invalid.
62
   */
63
  String getText( IndexRange indexes ) throws IndexOutOfBoundsException;
64
65
  /**
66
   * Moves the caret to the given document offset.
67
   *
68
   * @param offset The absolute offset into the document, zero-based.
69
   */
70
  void moveTo( final int offset );
71
72
  /**
73
   * Returns an object that can be used to track the current caret position
74
   * within the document.
75
   *
76
   * @return The caret's position, which is updated continuously.
77
   */
78
  Caret getCaret();
79
80
  /**
81
   * Replaces the text within the given range with the given string.
82
   *
83
   * @param indexes The starting and ending document indexes that represent
84
   *                the range of text to replace.
85
   * @param s       The text to replace, which can be shorter or longer than the
86
   *                specified range.
87
   */
88
  void replaceText( IndexRange indexes, String s );
89
90
  /**
91
   * Returns the starting and ending indexes into the document for the
92
   * word at the current caret position.
93
   * <p>
94
   * Finds the start and end indexes for the word in the current document,
95
   * where the caret is located. There are a few different scenarios, where
96
   * the caret can be at: the start, end, or middle of a word; also, the
97
   * caret can be at the end or beginning of a punctuated word; as well, the
98
   * caret could be at the beginning or end of the line or document.
99
   * </p>
100
   *
101
   * @return The start and ending index into the current document that
102
   * represent the word boundaries of the word under the caret.
103
   */
104
  IndexRange getCaretWord();
105
106
  /**
107
   * Convenience method to get the word at the current caret position.
108
   *
109
   * @return This will return the empty string if the caret is out of bounds.
110
   */
111
  default String getCaretWordText() {
112
    return getText( getCaretWord() );
113
  }
114
115
  /**
116
   * Requests undoing the last text-changing action.
117
   */
118
  void undo();
119
120
  /**
121
   * Requests redoing the last text-changing action that was undone.
122
   */
123
  void redo();
124
125
  /**
126
   * Requests cutting the selected text, or the current line if none selected.
127
   */
128
  void cut();
129
130
  /**
131
   * Requests copying the selected text, or no operation if none selected.
132
   */
133
  void copy();
134
135
  /**
136
   * Requests pasting from the clipboard into the editor. This will replace
137
   * text if selected, otherwise the clipboard contents are inserted at the
138
   * cursor.
139
   */
140
  void paste();
141
142
  /**
143
   * Requests selecting the entire document. This will replace the existing
144
   * selection, if any.
145
   */
146
  void selectAll();
147
148
  /**
149
   * Requests making the selected text, or word at caret, bold.
150
   */
151
  default void bold() { }
152
153
  /**
154
   * Requests making the selected text, or word at caret, italic.
155
   */
156
  default void italic() { }
157
158
  /**
159
   * Requests making the selected text, or word at caret, monospace.
160
   */
161
  default void monospace() { }
162
163
  /**
164
   * Requests making the selected text, or word at caret, a superscript.
165
   */
166
  default void superscript() { }
167
168
  /**
169
   * Requests making the selected text, or word at caret, a subscript.
170
   */
171
  default void subscript() { }
172
173
  /**
174
   * Requests making the selected text, or word at caret, struck.
175
   */
176
  default void strikethrough() { }
177
178
  /**
179
   * Requests making the selected text, or word at caret, a blockquote block.
180
   */
181
  default void blockquote() { }
182
183
  /**
184
   * Requests making the selected text, or word at caret, inline code.
185
   */
186
  default void code() { }
187
188
  /**
189
   * Requests making the selected text, or word at caret, a fenced code block.
190
   */
191
  default void fencedCodeBlock() { }
192
193
  /**
194
   * Requests making the selected text, or word at caret, a heading.
195
   *
196
   * @param level The heading level to apply (typically 1 through 3).
197
   */
198
  default void heading( final int level ) { }
199
200
  /**
201
   * Requests making the selected text, or word at caret, an unordered list
202
   * block.
203
   */
204
  default void unorderedList() { }
205
206
  /**
207
   * Requests making the selected text, or word at caret, an ordered list block.
208
   */
209
  default void orderedList() { }
210
211
  /**
212
   * Requests making the selected text, or inserting at the caret, a
213
   * horizontal rule.
214
   */
215
  default void horizontalRule() { }
216
}
1217
A src/main/java/com/keenwrite/editors/TextResource.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.editors;
3
4
import com.keenwrite.io.MediaType;
5
import javafx.beans.property.ReadOnlyBooleanProperty;
6
import javafx.scene.Node;
7
import org.mozilla.universalchardet.UniversalDetector;
8
9
import java.io.File;
10
import java.nio.charset.Charset;
11
import java.nio.file.Path;
12
13
import static com.keenwrite.constants.Constants.DEFAULT_CHARSET;
14
import static com.keenwrite.events.StatusEvent.clue;
15
import static java.nio.charset.Charset.forName;
16
import static java.nio.file.Files.readAllBytes;
17
import static java.nio.file.Files.write;
18
import static java.util.Arrays.asList;
19
import static java.util.Locale.ENGLISH;
20
21
/**
22
 * A text resource can be persisted and retrieved from its persisted location.
23
 */
24
public interface TextResource {
25
  /**
26
   * Sets the text string that to be changed through some graphical user
27
   * interface. For example, a YAML document must be parsed from the given
28
   * text string into a tree view with which the user may interact.
29
   *
30
   * @param text The new content for the resource.
31
   */
32
  void setText( String text );
33
34
  /**
35
   * Returns the text string that may have been modified by the user through
36
   * some graphical user interface.
37
   *
38
   * @return The text value, based on the value set from
39
   * {@link #setText(String)}, but possibly mutated.
40
   */
41
  String getText();
42
43
  /**
44
   * Return the character encoding for this file.
45
   *
46
   * @return A non-null character set, primarily detected from file contents.
47
   */
48
  Charset getEncoding();
49
50
  /**
51
   * Renames the current file to the given fully qualified file name.
52
   *
53
   * @param file The new file name.
54
   */
55
  void rename( final File file );
56
57
  /**
58
   * Returns the file name, without any directory components, for this instance.
59
   * Useful for showing as a tab title.
60
   *
61
   * @return The file name value returned from {@link #getFile()}.
62
   */
63
  default String getFilename() {
64
    final var filename = getFile().toPath().getFileName();
65
    return filename == null ? "" : filename.toString();
66
  }
67
68
  /**
69
   * Returns the fully qualified {@link File} to the editable text resource.
70
   * Useful for showing as a tab tooltip, saving the file, or reading it.
71
   *
72
   * @return A non-null {@link File} instance.
73
   */
74
  File getFile();
75
76
  /**
77
   * Returns the {@link MediaType} associated with the file being edited.
78
   *
79
   * @return The {@link MediaType} for the editor's file.
80
   */
81
  default MediaType getMediaType() {
82
    return MediaType.valueFrom( getFile() );
83
  }
84
85
  /**
86
   * Answers whether this instance is an editor for at least one of the given
87
   * {@link MediaType} references.
88
   *
89
   * @param mediaTypes The {@link MediaType} references to compare against.
90
   * @return {@code true} if the given list of media types contains the
91
   * {@link MediaType} for this editor.
92
   */
93
  default boolean isMediaType( final MediaType... mediaTypes ) {
94
    return asList( mediaTypes ).contains( getMediaType() );
95
  }
96
97
  /**
98
   * Returns the fully qualified {@link Path} to the editable text resource.
99
   * This delegates to {@link #getFile()}.
100
   *
101
   * @return A non-null {@link Path} instance.
102
   */
103
  default Path getPath() {
104
    return getFile().toPath();
105
  }
106
107
  /**
108
   * Read the file contents and update the text accordingly. If the file
109
   * cannot be read then no changes will happen to the text. Fails silently.
110
   *
111
   * @param path The fully qualified {@link Path}, including a file name, to
112
   *             fully read into the editor.
113
   * @return The character encoding for the file at the given {@link Path}.
114
   */
115
  default Charset open( final Path path ) {
116
    final var file = path.toFile();
117
    Charset encoding = DEFAULT_CHARSET;
118
119
    try {
120
      if( file.exists() ) {
121
        if( file.canWrite() && file.canRead() ) {
122
          final var bytes = readAllBytes( path );
123
          encoding = detectEncoding( bytes );
124
125
          setText( asString( bytes, encoding ) );
126
        }
127
        else {
128
          clue( "TextResource.load.error.permissions", file.toString() );
129
        }
130
      }
131
      else {
132
        clue( "TextResource.load.error.unsaved", file.toString() );
133
      }
134
    } catch( final Exception ex ) {
135
      clue( ex );
136
    }
137
138
    return encoding;
139
  }
140
141
  /**
142
   * Read the file contents and update the text accordingly. If the file
143
   * cannot be read then no changes will happen to the text. This delegates
144
   * to {@link #open(Path)}.
145
   *
146
   * @param file The {@link File} to fully read into the editor.
147
   * @return The file's character encoding.
148
   */
149
  default Charset open( final File file ) {
150
    return open( file.toPath() );
151
  }
152
153
  /**
154
   * Save the file contents and clear the modified flag. If the file cannot
155
   * be saved, the exception is swallowed and this method returns {@code false}.
156
   *
157
   * @return {@code true} the file was saved; {@code false} if upon exception.
158
   */
159
  default boolean save() {
160
    try {
161
      write( getPath(), asBytes( getText() ) );
162
      clearModifiedProperty();
163
      return true;
164
    } catch( final Exception ex ) {
165
      clue( ex );
166
    }
167
168
    return false;
169
  }
170
171
  /**
172
   * Returns the node associated with this {@link TextResource}.
173
   *
174
   * @return The view component for the {@link TextResource}.
175
   */
176
  Node getNode();
177
178
  /**
179
   * Answers whether the resource has been modified.
180
   *
181
   * @return {@code true} the resource has changed; {@code false} means that
182
   * no changes to the resource have been made.
183
   */
184
  default boolean isModified() {
185
    return modifiedProperty().get();
186
  }
187
188
  /**
189
   * Returns a property that answers whether this text resource has been
190
   * changed from the original text that was opened.
191
   *
192
   * @return A property representing the modified state of this
193
   * {@link TextResource}.
194
   */
195
  ReadOnlyBooleanProperty modifiedProperty();
196
197
  /**
198
   * Lowers the modified flag such that listeners to the modified property
199
   * will be informed that the text that's being edited no longer differs
200
   * from what's persisted.
201
   */
202
  void clearModifiedProperty();
203
204
  private String asString( final byte[] text, final Charset encoding ) {
205
    return new String( text, encoding );
206
  }
207
208
  /**
209
   * Converts the given string to an array of bytes using the encoding that was
210
   * originally detected (if any) and associated with this file.
211
   *
212
   * @param text The text to convert into the original file encoding.
213
   * @return A series of bytes ready for writing to a file.
214
   */
215
  private byte[] asBytes( final String text ) {
216
    return text.getBytes( getEncoding() );
217
  }
218
219
  private Charset detectEncoding( final byte[] bytes ) {
220
    final var detector = new UniversalDetector( null );
221
    detector.handleData( bytes, 0, bytes.length );
222
    detector.dataEnd();
223
224
    final var charset = detector.getDetectedCharset();
225
226
    return charset == null
227
      ? DEFAULT_CHARSET
228
      : forName( charset.toUpperCase( ENGLISH ) );
229
  }
230
}
1231
A src/main/java/com/keenwrite/editors/definition/DefinitionEditor.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.editors.definition;
3
4
import com.keenwrite.constants.Constants;
5
import com.keenwrite.editors.TextDefinition;
6
import com.keenwrite.sigils.Tokens;
7
import com.keenwrite.ui.tree.AltTreeView;
8
import com.keenwrite.ui.tree.TreeItemConverter;
9
import javafx.beans.property.BooleanProperty;
10
import javafx.beans.property.ReadOnlyBooleanProperty;
11
import javafx.beans.property.SimpleBooleanProperty;
12
import javafx.beans.value.ObservableValue
13
import java.io.File;
14
import java.nio.charset.Charset;
15
import java.util.*;
16
import java.util.regex.Pattern;
17
18
import static com.kconstants.Constants.*;events.StatusEvent.clue;events.TextDefinitionFocusEvent.fireTextDefinitionFocus;ui.fonts.IconFactory.createGraphic.lang.String.format.util.regex.Pattern.compile.util.regex.Pattern.quoteTOP_CENTERscene.control.scene.control.scene.control.TreeItem.valueChangedEventdocument parserTransformEditor extends BorderPane
19
  implements TextDefinition {
20
  private static final int GROUP_DELIMITED = 1;
21
22
  /**
23
   * Contains the root that is added to the view.
24
   */
25
  private finalmTreeRoot = createRootTreeItem();
26
    new AltTreeView<>( mTreeRoot, new TreeItemConverter() );
27
28
  /**
29
   * Used to adapt the structured document into a {@link TTransformer mTreeTransformerFile being edited by this editor instance.
30
   */
31
  private File mFile;
32
33
  /**
34
   * Opened file's character encoding, or {@link Constants#DEFAULT_CHARSET} if
35
   * either no encoding could be determined or this is a new (empty) file.
36
   */
37
  private final Charset mEncoding;
38
39
  /**
40
   * Tracks whether the in-memory definitions have changed with respect to the
41
   * persisted definitBooleanProperty mModified = new SimpleBooleanProperty();
42
43
  /**
44
   * This is provided for unit tests that are not backed by filestreeTransformer Responsible for transforming the definitions into
45
   *{@link TreeItem} instancesEditor(
46
    final TreeTransformer treeTransformer ) {
47
    this( DEFINITION_DEFAULT, treeTransformer );
48
  }file The file of definitions to maintain through the UIEditor(
49
    final File file,
50
    final TreeTransformer treeTransformer ) {
51
    assert file != null;
52
    assert treeTransformer != null;
53
54
    mFile = file;
55
    mTreeTransformer = treeTransformer;
56
57
    //mTreeView.setCellFactory( new TreeCellFactory() );
58
    mTmTmTreeView.focusedProperty().addListener( this::focused
59
      createButton( "create", e -> createDefinition() ),
60
      createButton( "rename", e -> renameDefinition() ),
61
      createButton( "delete", e -> deleteDefinitions()UI_CONTROL_SPACINGmTTOP_CENTER );
62
    mEncoding = open( mFile );
63
64
    // After the file is opened, watch for changes, not before. Otherwise,
65
    // upon saving, users will be prompted to save a file that hasn't had
66
    // any modifications (from their perspective).
67
    addT event -> mModified.set( true ) )setText( final String document ) {
68
    final var foster = mTreeTransformer.transform( document );
69
    final var biological = getTreefosterbiological.getChildren().add( child );
70
    }
71
72
    getTreeView().refresh()String getText() {
73
    final var result = new StringBuilder( 32768 );
74
75
    try {
76
   = isTreeWellFormed();
77
78
      problem.ifPresentOrElse(
79
        ( node ) -> clue( "yaml.error.tree.form", node ),
80
        () -> result.append( mTreeTransformer.transform( root ) )
81
      );
82
    } catch( final Exception ex ) {
83
      // Catch errors while checking for a well-formed tree (e.g., stack smash).
84
      // Also catch any transformation exceptions (e.g., Json processing).
85
      clue( ex );
86
    }
87
88
    return result.toString()File getFile() {
89
    return mFilename( final File file ) {
90
    mFile = fileCharset getEncoding() {
91
    return mEncodingReadOnlyBooleanProperty modifiedProperty() {
92
    return mModifiedclearModifiedProperty() {
93
    mModified.setValue( falsefinal String msgKey,Constants.ACTION_PREFIX + "definititext" ) );
94
    final var graphic = createGraphic( get( keyPrefix + ".icon" ) );
95
    button.setGraphic( graphicnew TreeItemMapper()interpolate(
96
    finalmap, final Tokens tokens ) {
97
98
    // Non-greedy match of key names delimited by definition tokens.
99
    final var pattern = compile(
100
      format( "(%s.*?%s)",
101
              quote( tokens.getBegan() ),
102
              quote( tokens.getEnded() )
103
      )
104
    );
105
106
    map.replaceAll( ( k, v ) -> resolve( map, v, pattern ) );
107
    return map;
108
  }
109
110
  /**
111
   * Given a value with zero or more key references, this will resolve all
112
   * the values, recursively. If a key cannot be de-referenced, the value will
113
   * contain the key namemap     Map to search for keys when resolving key references.
114
   * @param value   Value containing zero or more key references.
115
   * @param pattern The regular expression pattern to match variable key names.
116
   * @return The given value with all embedded key references interpolated.
117
   */
118
  private String resolve(
119
    finalmap, String value, final Pattern pattern ) {
120
    final var matcher = pattern.matcher( value );
121
122
    while( matcher.find() ) {
123
 keyName = matcher.group( GROUP_DELIMITED );
124
      final var mapValue = map.get( keyName );
125
      final var keyValue = mapValue == null
126
        ? keyName
127
        : resolve( map, mapValue, pattern );
128
129
      value = value.replace( keyName, keyValue );
130
    }
131
132
    return value;
133
  }
134
Optional<TreeItem<String>Optional.ofNullable( problemChild )Optional.empty@Override
135
  public void renameDefinition@Override
136
  public void deleteDefinition@Override
137
  public void createDefinitionDefinitionvarvarACTION_PREFIX + "definition.create.text" )
138
createDefinition() );ACTION_PREFIX + "definition.rename.text" )
139
renameDefinition() );ACTION_PREFIX + "definition.delete.text" )
140
 -> {}
141
142
        case DELETE -> deleteDefinitions();
143
        case INSERT -> createDefinition();
144
145
        case R -> {
146
          if( evrenameDefinition();
147
          }
148
        }Called when the editor's input focus changes. This will fire an event
149
   * for subscribersignored Not used.
150
   * @param o       The old input focus property value.
151
   * @param n       The new input focus property valuefocused(
152
    final ObservableValue<? extends Boolean> ignored,
153
    final Boolean o,
154
    final Boolean n ) {
155
    if( n != null && n ) {
156
      fireTextDefinitionFocus( this/**
157
   * Creates a new {@link TreeItem} that is intended to be the root-level item
158
   * added to. This allows the root item to be
159
   * distinguished from the other items so that reference keys do not include
160
   * "Definition" as part of their namA new {@link TreeItem}/
161
  private RootTreeItem<String> createRootnew RootTreeItem<>(createDefinition//@Override!node.isLeaf@Overridethe actively selected item inselected item, or the tree root item if no item is selected.
162
   */Root}
1163
A src/main/java/com/keenwrite/editors/definition/DefinitionTreeItem.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.editorsfinal String text,
3
4
     new TreeItemMapper().toPath( getParent()Answers whether there are any definitions in this tree{@code true} when there are no definitions in the tree; {@code
5
   * false} when there is at least one definition present.
6
   */
7
  public boolean isEmpty() {
8
    return getChildren().isEmpty();
9
  }
10
}
111
A src/main/java/com/keenwrite/editors/definition/RootTreeItem.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.editors.definition;
3
4
import javafx.scene.control.TreeItem;
5
import javafx.scene.control.TreeView;
6
7
/**
8
 * Marker interface for top-most {@link TreeItem}. This class allows the
9
 * {@link TreeItemMapper} to ignore the topmost definition. Such contortions
10
 * are necessary because {@link TreeView} requires a root item that isn't part
11
 * of the user's definition file.
12
 * <p>
13
 * Another approach would be to associate object pairs per {@link TreeItem},
14
 * but that would be a waste of memory since the only "exception" case is
15
 * the root {@link TreeItem}.
16
 * </p>
17
 *
18
 * @param <T> The type of {@link TreeItem} to store in the {@link TreeView}.
19
 */
20
public final class RootTreeItem<T> extends DefinitionTreeItem<T> {
21
  /**
22
   * Default constructor, calls the superclass, no other behaviour.
23
   *
24
   * @param value The {@link TreeItem} node name to construct the superclass.
25
   * @see TreeItemMapper#toMap(TreeItem) for details on how this
26
   * class is used.
27
   */
28
  public RootTreeItem( final T value ) {
29
    super( value );
30
  }
31
}
132
A src/main/java/com/keenwrite/editors/definition/TreeItemMapper.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.editorskeenwrite.preview.HtmlPreview
3
import static com.keenwrite.constants.Constants.MAP_SIZE_DEFAULTtmlPreview/
4
public final class TreeItemMapper {
5
  /**
6
   * Separates definition key})ublic TreeItemMappevar map = new HashMap<String, String>( MAP_SIZE_DEFAULT );
7
    final vavavar stack = new Stack<TreeItem<T>varkey.toString();
8
  }
9
}
110
A src/main/java/com/keenwrite/editors/definition/TreeTransformer.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.editors.definition;
3
4
import javafx.scene.control.TreeItem;
15
6
/**
7
 * 
A src/main/java/com/keenwrite/editors/definition/package-info.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
3
/**
4
 * This package contains classes that pertain to hierarchical, structured
5
 * data formats, which can be used as interpolated variables.
6
 */
7
package com.keenwrite.editors.definition;
18
A src/main/java/com/keenwrite/editors/definition/yaml/YamlTreeTransformer.java
1
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.editorsObjectMapperkeenwrite.events.StatusEvent.clueclue( ex );
A src/main/java/com/keenwrite/editors/definition/yaml/package-info.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
3
/**
4
 * This package contains classes that can parse YAML documents into a GUI
5
 * representation.
6
 */
7
package com.keenwrite.editors.def.yaml;
18
A src/main/java/com/keenwrite/editors/markdown/HyperlinkModel.java
1
1
/* Copyright 2020-2021 -- All rights reserved. */
2
package com.keenwrite, url, and titlefinal
A src/main/java/com/keenwrite/editors/markdown/LinkVisitor.java
1
1
/*
2
 * Copyright 2020-2021 White Magic Software, Ltd.
3
 *
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions are met:
8
 *
9
 *  o Redfinal
A src/main/java/com/keenwrite/editors/markdown/MarkdownEditor.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.editors.markdown;
3
4
import com.keenwrite.ConstantsdTextEditor;
5
importconstantst com.keenwrite.io.MediaType}
16
A src/main/java/com/keenwrite/events/AppEvent.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.events;
3
4
import static com.keenwrite.
5
/**
6
 * Marker interface for all application events.
7
 */
8
public interface AppEvent {default}
19
A src/main/java/com/keenwrite/events/Bus.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.events;
3
4
import org.greenrobot.eventbus.EventBus;
15
6
/**
7
 * Responsible for delegating interactions to the event bus library. This
8
 * class decouples the rest
9
    .builder().logNoSubscriberMessages( false ).installDefaultEventBus
A src/main/java/com/keenwrite/events/CaretNavigationEvent.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.events;
3
4
import com.keenwrite.ui.outline.DocumentOutline;
5
6
/**
7
 * Collates information about a caret event, which is typically triggered when
8
 * the user double-clicks in the {@link DocumentOutline}.
9
 */
10
public class CaretNavigationEvent implements AppEvent {
11
  /**
12
   * Absolute document offset.
13
   */
14
  private final int mOffset;
15
16
  private CaretNavigationEvent( final int offset ) {
17
    mOffset = offset;
18
  }
19
20
  /**
21
   * Publishes an event that requests moving the caret to the given offset.
22
   *
23
   * @param offset Move the caret to this document offset.
24
   */
25
  public static void fireCaretNavigationEvent( final int offset ) {
26
    new CaretNavigationEvent( offset ).fire();
27
  }
28
29
  public int getOffset() {
30
    return mOffset;
31
  }
32
}
133
A src/main/java/com/keenwrite/events/DocumentChangedEvent.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.events;
3
4
import org.jsoup.nodes.Document;
5
6
import static com.keenwrite.util.MurmurHash.hash32;
7
import static java.lang.System.currentTimeMillis;
8
9
/**
10
 * Collates information about an HTML document that has changed.
11
 */
12
public class DocumentChangedEvent implements AppEvent {
13
  private static final int SEED = (int) currentTimeMillis();
14
15
  private final String mText;
16
17
  /**
18
   * Hash the document so subscribers are only informed upon changes.
19
   */
20
  private static int sHash;
21
22
  /**
23
   * Creates an event with the new plain text document, having all variables
24
   * substituted and all markup removed.
25
   *
26
   * @param text The document text that has changed since the last time this
27
   *             type of event was fired.
28
   */
29
  private DocumentChangedEvent( final String text ) {
30
    mText = text;
31
  }
32
33
  /**
34
   * When the given document may have changed. This will only fire a change
35
   * event if the given document has changed from the last time this
36
   * event was fired. The document is first converted to plain text before
37
   * the comparison is made.
38
   *
39
   * @param html The document that may have changed.
40
   */
41
  public static void fireDocumentChangedEvent( final Document html ) {
42
    final var text = html.wholeText();
43
    final var hash = hash32( text, 0, text.length(), SEED );
44
45
    if( hash != sHash ) {
46
      sHash = hash;
47
      new DocumentChangedEvent( text ).fire();
48
    }
49
  }
50
51
  /**
52
   * Returns the text that has changed.
53
   *
54
   * @return The new document text.
55
   */
56
  public String getDocument() {
57
    return mText;
58
  }
59
60
  /**
61
   * Returns the document.
62
   *
63
   * @return The value from {@link #getDocument()}.
64
   */
65
  @Override
66
  public String toString() {
67
    return getDocument();
68
  }
69
}
170
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/FileOpenEvent.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.events;
3
4
import com.keenwrite.preview.HtmlPanel;
5
6
import java.net.URI;
7
8
/**
9
 * Collates information about a file requested to be opened. This can be called
10
 * when the user clicks a hyperlink in the {@link HtmlPanel}.
11
 */
12
public class FileOpenEvent implements AppEvent {
13
  private final URI mUri;
14
15
  private FileOpenEvent( final URI uri ) {
16
    assert uri != null;
17
    mUri = uri;
18
  }
19
20
  /**
21
   * Fires a new file open event using the given {@link URI} instance.
22
   *
23
   * @param uri The instance of {@link URI} to open as a file in a text editor.
24
   */
25
  public static void fireFileOpenEvent( final URI uri ) {
26
    new FileOpenEvent( uri ).fire();
27
  }
28
29
  /**
30
   * Returns the requested file name to be opened.
31
   *
32
   * @return A file reference that can be opened in a text editor.
33
   */
34
  public URI getUri() {
35
    return mUri;
36
  }
37
}
138
A src/main/java/com/keenwrite/events/FocusEvent.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.events;
3
4
/**
5
 * Collates information about an object that has gained focus. This is typically
6
 * used by text resource editors (such as text editors and definition editors).
7
 */
8
public class FocusEvent<T> implements AppEvent {
9
  private final T mNode;
10
11
  protected FocusEvent( final T node ) {
12
    mNode = node;
13
  }
14
15
  /**
16
   * This method is used to help update the UI whenever a component has gained
17
   * input focus.
18
   *
19
   * @return The object that has gained focus.
20
   */
21
  public T get() {
22
    return mNode;
23
  }
24
}
125
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
A src/main/java/com/keenwrite/events/ParseHeadingEvent.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.events;
3
4
import com.keenwrite.processors.Processor;
5
6
/**
7
 * Collates information about a document heading that has been parsed, after
8
 * all pertinent {@link Processor}s applied.
9
 */
10
public class ParseHeadingEvent implements AppEvent {
11
  private static final int NEW_OUTLINE_LEVEL = 0;
12
13
  /**
14
   * The heading text, which may be {@code null} upon creating a new outline.
15
   */
16
  private final String mText;
17
18
  /**
19
   * The heading level, which will be set to {@link #NEW_OUTLINE_LEVEL} if this
20
   * event indicates that the existing outline should be cleared anew.
21
   */
22
  private final int mLevel;
23
24
  /**
25
   * Offset into the text where the heading is found.
26
   */
27
  private final int mOffset;
28
29
  private ParseHeadingEvent(
30
    final int level, final String text, final int offset ) {
31
    mText = text;
32
    mLevel = level;
33
    mOffset = offset;
34
  }
35
36
  /**
37
   * Call to indicate a new outline is to be created.
38
   */
39
  public static void fireNewOutlineEvent() {
40
    new ParseHeadingEvent( NEW_OUTLINE_LEVEL, "Document", 0 ).fire();
41
  }
42
43
  /**
44
   * Call to indicate that a new heading must be added to the document outline.
45
   *
46
   * @param text   The heading text (parsed and processed).
47
   * @param level  A value between 1 and 6.
48
   * @param offset Absolute offset into document where heading is found.
49
   */
50
  public static void fireNewHeadingEvent(
51
    final int level, final String text, final int offset ) {
52
    assert text != null;
53
    assert 1 <= level && level <= 6;
54
    assert 0 <= offset;
55
    new ParseHeadingEvent( level, text, offset ).fire();
56
  }
57
58
  public boolean isNewOutline() {
59
    return getLevel() == NEW_OUTLINE_LEVEL;
60
  }
61
62
  public int getLevel() {
63
    return mLevel;
64
  }
65
66
  /**
67
   * Returns the text description for the heading.
68
   *
69
   * @return The post-parsed and processed heading text from the document.
70
   */
71
  public String getText() {
72
    return mText;
73
  }
74
75
  /**
76
   * Returns an offset into the document where the heading is found.
77
   *
78
   * @return A zero-based document offset.
79
   */
80
  public int getOffset() {
81
    return mOffset;
82
  }
83
84
  @Override
85
  public String toString() {
86
    return getText();
87
  }
88
}
189
A src/main/java/com/keenwrite/events/ScrollLockEvent.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.events;
3
4
import static java.awt.Toolkit.getDefaultToolkit;
5
import static java.awt.event.KeyEvent.VK_SCROLL_LOCK;
6
7
/**
8
 * Collates information about the scroll lock status.
9
 */
10
public class ScrollLockEvent implements AppEvent {
11
  private final boolean mLocked;
12
13
  private ScrollLockEvent( final boolean locked ) {
14
    mLocked = locked;
15
  }
16
17
  /**
18
   * Fires a scroll lock event provided that the scroll lock key is in the
19
   * off state.
20
   *
21
   * @param locked The new locked status.
22
   */
23
  public static void fireScrollLockEvent( final boolean locked ) {
24
    // If the scroll lock key is off, allow the status to change.
25
    if( !getScrollLockKeyStatus() ) {
26
      fire( locked );
27
    }
28
  }
29
30
  /**
31
   * Fires a scroll lock event based on the current status of the scroll
32
   * lock key.
33
   */
34
  public static void fireScrollLockEvent() {
35
    fire( getScrollLockKeyStatus() );
36
  }
37
38
  /**
39
   * Answers whether the synchronized scrolling should be locked in place
40
   * (i.e., prevent sync scrolling).
41
   *
42
   * @return {@code true} when the user has locked the scrollbar position.
43
   */
44
  public boolean isLocked() {
45
    return mLocked;
46
  }
47
48
  private static void fire( final boolean locked ) {
49
    new ScrollLockEvent( locked ).fire();
50
  }
51
52
  /**
53
   * Returns the state of the scroll lock key.
54
   *
55
   * @return {@code true} when the scroll lock key is in the on state.
56
   */
57
  private static boolean getScrollLockKeyStatus() {
58
    return getDefaultToolkit().getLockingKeyState( VK_SCROLL_LOCK );
59
  }
60
}
161
A src/main/java/com/keenwrite/events/StatusEvent.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.events;
3
4
import com.keenwrite.MainApp;
5
6
import java.util.List;
7
import java.util.stream.Collectors;
8
9
import static com.keenwrite.Messages.get;
10
import static com.keenwrite.constantsfinalnull;
11
  }
12
13
  public StatusEvent(this( "", problem );
14
  }
15
assert problem@Override
16
  public String toString() {
17
    return format( "%s%s%s",
18
                   mMessage,
19
                   mMessage.isBlank() ? "" : " ",
20
                  assert problem != null;
121
22
    // Subclasses of RuntimeException must be subject to Englishification.
23
    if( problem.getClass().equals( RuntimeException.class ) ) {
24
      final var cause = problem.getCause();
25
      return cause == null ?: cause.getMessage()Notifies listeners of a series of messages. This is useful when providing
26
   * users feedback of how third-party executables have faileds The lines of text to displayList<String> messages ) {
27
    messages.forEach( StatusEvent::fireStatusEventNotifies listeners of an error.
28
   *
29
   * @param key The message bundle key to look up.
30
   * @param t   The exception that caused the errorThrowable t ), tNotifies listeners ofNotifies listeners of
31
   *problem
A src/main/java/com/keenwrite/events/TextDefinitionFocusEvent.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.events;
3
4
import com.keenwrite.editors.TextDefinition;
15
6
public class TextDefinitionDefinition> {
7
  protected TextDefinitionDefinitionDefinition} editor
8
   * subscribers may perform an actionDefinitionFocus( final TextDefinition editor ) {
9
    new TextDefinition
A src/main/java/com/keenwrite/events/TextEditorFocusEvent.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.events;
3
4
import com.keenwrite.editors.TextEditor;
5
6
TextEditorFocusfire();
7
  }
8
}
19
A src/main/java/com/keenwrite/events/WordCountEvent.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.events;
3
4
/**
5
 * Collates information about the word count changing.
6
 */
7
public class WordCountEvent implements AppEvent {
8
  /**
9
   * Number of words in the document.
10
   */
11
  private final int mCount;
12
13
  private WordCountEvent( final int count ) {
14
    mCount = count;
15
  }
16
17
  /**
18
   * Publishes an event that indicates the number of words in the document.
19
   *
20
   * @param count The approximate number of words in the document.
21
   */
22
  public static void fireWordCountEvent( final int count ) {
23
    new WordCountEvent( count ).fire();
24
  }
25
26
  public int getCount() {
27
    return mCount;
28
  }
29
}
130
A src/main/java/com/keenwrite/exceptions/MissingFileException.java
1
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved.final
A src/main/java/com/keenwrite/heuristics/package-info.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
3
/**
4
 * This package contains classes to help with word count. In logographic,
5
 * or other non-alphabetic languages, word tokenization cannot rely on
6
 * spaces. Instead, we need to employ a more sophisticated approach using
7
 * natural language parsing (NLP).
8
 */
9
package com.keenwrite.heuristics;
110
A src/main/java/com/keenwrite/io/FileEvent.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.io;
3
4
import java.io.File;
5
import java.util.EventObject;
6
7
/**
8
 * Responsible for indicating that a file has been modified by the file system.
9
 */
10
public class FileEvent extends EventObject {
11
12
  /**
13
   * Constructs a new event that indicates the source of a file system event.
14
   *
15
   * @param file The {@link File} that has succumb to a file system event.
16
   */
17
  public FileEvent( final File file ) {
18
    super( file );
19
  }
20
21
  /**
22
   * Returns the source as an instance of {@link File}.
23
   *
24
   * @return The {@link File} being watched.
25
   */
26
  public File getFile() {
27
    return (File) getSource();
28
  }
29
}
130
A src/main/java/com/keenwrite/io/FileModifiedListener.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.io;
3
4
import java.util.EventListener;
5
import java.util.function.Consumer;
6
7
/**
8
 * Responsible for informing listeners when a file has been modified.
9
 */
10
public interface FileModifiedListener
11
  extends EventListener, Consumer<FileEvent> {
12
}
113
A src/main/java/com/keenwrite/io/FileType.java
1
1
/* Copyright 2020-2021 -- All rights reserved. */
2
package com.keenwrite.io {@code
3
 * settings.properties}
A src/main/java/com/keenwrite/io/FileWatchService.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.io;
3
4
import org.renjin.repackaged.guava.collect.BiMap;
5
import org.renjin.repackaged.guava.collect.HashBiMap;
6
7
import java.io.File;
8
import java.io.IOExceptioFileSystems.getDefault;mWatchService = createtry {
9
  private WatchService createWatchService() {
10
    try {
11
      return return  }
12
}
113
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
im url
12
      if( url.openConnection()conn ) {
13
        cccccccconn.connect();
114
15
  cConn = conn;
A src/main/java/com/keenwrite/io/MediaType.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.io;
3
4
import java.io.File;
5
import java.io.IOException;
6
import java.nio.file.Path;
7
8
import static com.keenwrite.io.MediaType.TypeName.*;
9
import static com.keeAPP_DOCUMENT_OUTLINE( ),
10
  APP_DOCUMENT_STATISTICS(statistics" ),
11
12
  APP_ACAD( APPLICATION, "acad" ),
13
  APP_JAVA_OBJECT( ),
14
  APP_JAVA( APPLICATION, "java" ),
15
  APP_PS( APPLICATION, "postscript" ),
16
  APP_EPS( APPLICATION, "eps" ),
17
  APP_PDF( APPLICATION, "pdf" ),
18
  APP_ZIP( APPLICATION, "zip"PHOTOSHOP( "photoshop  IMAGE_X_BITMAP( "x-xbitmap" ),
19
  IMAGE_X_PIXMAP( "x-xpixmap"audio types.
20
   */
21
  AUDIO_BASIC( AUDIO, "basic" ),
22
  AUDIO_MP3( AUDIO, "mp3" ),
23
  AUDIO_WAV( AUDIO, "x-wav"video types.
24
   */
25
  VIDEO_MNG( VIDEO, "x-mngAUDIO,
26
    VIDEOassert file != null;assert filename != null;assert path != null;, may be {@code null}if( header == null || header.isBlank() ) {
27
      return UNDEFINED;
28
    }
29
assert type != null;
30
    assert subtype != null;
31
assert type != null;
32
    assert subtype != null;
33
Undefined() {
34
    return this == UNDEFINEDassert prefix != null;
135
A src/main/java/com/keenwrite/io/MediaTypeExtension.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.io;
3
4
import java.util.List;
5
6
import static com.keenwrite.io.MediaType.*;
7
import static java.util.List.of;
8
9
/**
10
 * Responsible for associating file extensionACAD( APP_ACAD, of( "dwg" ) ),  MEDIA_APP_PS( APP_PS, of( "ps" ) ),
11
  MEDIA_APP_EPS( APP_EPS ),
12
  MEDIA_APP_ZIP( APP_ZIP ),
13
14
  MEDIA_AUDIO_MP3( AUDIO_MP3 ),
15
  MEDIA_AUDIO_BASIC( AUDIO_BASIC, of( "au" ) ),
16
  MEDIA_AUDIO_WAV( AUDIO_WAV, of( "wav" )PSD( IMAGE_PHOTOSHOP, of( "psd  MEDIA_IMAGE_X_BITMAP( IMAGE_X_BITMAP, of( "xbmX_PIXMAP( IMAGE_X_PIXMAP, of( "xpm" ) ),
117
18
  MEDIA_VIDEO_MNG( VIDEO_MNG, of( "mng" )
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;
17
8
import static com.keenSysSys
9
   *SysSys
A src/main/java/com/keenwrite/io/PollingWatchService.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.io;
3
4
import java.nio.file.WatchEvent;
5
import java.nio.file.WatchKey;
6
import java.nio.file.WatchService;
7
import java.nio.file.Watchable;
8
import java.util.List;
9
import java.util.concurrent.TimeUnit;
10
11
/**
12
 * Responsible for polling the file system to see whether a file has been
13
 * updated. This is instantiated when an instance of {@link WatchService}
14
 * cannot be created using the Java API.
15
 * <p>
16
 * This is a skeleton class to avoid {@code null} references. In theory,
17
 * it should never get instantiated. If the application is run on a system
18
 * that does not support file system events, this should eliminate NPEs.
19
 * </p>
20
 */
21
public class PollingWatchService implements WatchService {
22
  private final WatchKey EMPTY_KEY = new WatchKey() {
23
    private final Watchable WATCHABLE = new Watchable() {
24
      @Override
25
      public WatchKey register(
26
        final WatchService watcher,
27
        final WatchEvent.Kind<?>[] events,
28
        final WatchEvent.Modifier... modifiers ) {
29
        return EMPTY_KEY;
30
      }
31
32
      @Override
33
      public WatchKey register(
34
        final WatchService watcher, final WatchEvent.Kind<?>... events ) {
35
        return EMPTY_KEY;
36
      }
37
    };
38
39
    @Override
40
    public boolean isValid() {
41
      return false;
42
    }
43
44
    @Override
45
    public List<WatchEvent<?>> pollEvents() {
46
      return List.of();
47
    }
48
49
    @Override
50
    public boolean reset() {
51
      return false;
52
    }
53
54
    @Override
55
    public void cancel() {
56
    }
57
58
    @Override
59
    public Watchable watchable() {
60
      return WATCHABLE;
61
    }
62
  };
63
64
  @Override
65
  public void close() {
66
  }
67
68
  @Override
69
  public WatchKey poll() {
70
    return EMPTY_KEY;
71
  }
72
73
  @Override
74
  public WatchKey poll( final long timeout, final TimeUnit unit ) {
75
    return EMPTY_KEY;
76
  }
77
78
  @Override
79
  public WatchKey take() {
80
    return EMPTY_KEY;
81
  }
82
}
183
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
A src/main/java/com/keenwrite/predicates/PredicateFactory.java
1
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved.final
A src/main/java/com/keenwrite/preferences/FileProperty.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.preferences;
3
4
import javafx.beans.property.SimpleObjectProperty;
5
6
import java.io.File;
17
8
public final class FileProperty extends SimpleObjectProperty<File
A src/main/java/com/keenwrite/preferences/Key.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.preferences;
3
4
/**
5
 * Responsible for creating a type hierarchy of preference storage keys.
6
 */
7
public class Key {
8
  private final Key mParent;
9
  private final String mName;
10
11
  private Key( final Key parent, final String name ) {
12
    mParent = parent;
13
    mName = name;
14
  }
15
16
  /**
17
   * Returns a new key with no parent.
18
   *
19
   * @param name The key name, never {@code null}.
20
   * @return The new {@link Key} instance with a name but no parent.
21
   */
22
  public static Key key( final String name ) {
23
    assert name != null && !name.isEmpty();
24
    return key( null, name );
25
  }
26
27
  /**
28
   * Returns a new key with a given parent.
29
   *
30
   * @param parent The parent of this {@link Key}, or {@code null} if this is
31
   *               the topmost key in the chain.
32
   * @param name   The key name, never {@code null}.
33
   * @return The new {@link Key} instance with a name and parent.
34
   */
35
  public static Key key( final Key parent, final String name ) {
36
    assert name != null && !name.isEmpty();
37
    return new Key( parent, name );
38
  }
39
40
  private Key parent() {
41
    return mParent;
42
  }
43
44
  private String name() {
45
    return mName;
46
  }
47
48
  /**
49
   * Returns a dot-separated path representing the key's name.
50
   *
51
   * @return The recursively derived dot-separated key name.
52
   */
53
  @Override
54
  public String toString() {
55
    return parent() == null ? name() : parent().toString() + '.' + name();
56
  }
57
}
158
A src/main/java/com/keenwrite/preferences/LocaleProperty.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.preferences;
3
4
import javafx.beans.property.SimpleObjectProperty;
5
import javafx.collections.ObservableList;
6
7
import java.util.LinkedHashMap;
8
import java.util.Locale;
9
import java.util.Map;
10
import java.util.Objects;
11
12
import static com.keenwrite.constants.Constants.LOCALE_DEFAULT;
13
import static com.keenwrite.preferences.Workspace.listProperty;
14
import static java.util.Locale.forLanguageTag;
15
16
/**
17
 * Responsible for providing a list of locales from which the user may pick.
18
 */
19
public final class LocaleProperty extends SimpleObjectProperty<String> {
20
21
  /**
22
   * Lists the locales having fonts that are supported by the application.
23
   * When the Markdown and preview CSS files are loaded, a general file is
24
   * first loaded, then a specific file is loaded according to the locale.
25
   * The specific file overrides font families so that different languages
26
   * may be presented.
27
   * <p>
28
   * Using an instance of {@link LinkedHashMap} preserves display order.
29
   * </p>
30
   * <p>
31
   * See
32
   * <a href="https://www.oracle.com/java/technologies/javase/jdk12locales.html">JDK 12 Locales</a>
33
   * for details.
34
   * </p>
35
   */
36
  private static final Map<String, Locale> sLocales = new LinkedHashMap<>();
37
38
  static {
39
    final String[] tags = {
40
      "en-Latn-AU",
41
      "en-Latn-CA",
42
      "en-Latn-GB",
43
      "en-Latn-NZ",
44
      "en-Latn-US",
45
      "en-Latn-ZA",
46
      "ja-Jpan-JP",
47
      "ko-Kore-KR",
48
      "zh-Hans-CN",
49
      "zh-Hans-SG",
50
      "zh-Hant-HK",
51
      "zh-Hant-TW",
52
    };
53
54
    for( final var tag : tags ) {
55
      final var locale = forLanguageTag( tag );
56
      sLocales.put( locale.getDisplayName(), locale );
57
    }
58
  }
59
60
  public LocaleProperty( final Locale locale ) {
61
    super( sanitize( locale ).getDisplayName() );
62
  }
63
64
  public static String parseLocale( final String languageTag ) {
65
    final var locale = forLanguageTag( languageTag );
66
    final var key = getKey( sLocales, locale );
67
    return key == null ? LOCALE_DEFAULT.getDisplayName() : key;
68
  }
69
70
  public static String toLanguageTag( final String displayName ) {
71
    return sLocales.getOrDefault( displayName, LOCALE_DEFAULT ).toLanguageTag();
72
  }
73
74
  public Locale toLocale() {
75
    return sLocales.getOrDefault( getValue(), LOCALE_DEFAULT );
76
  }
77
78
  private static Locale sanitize( final Locale locale ) {
79
    // If the language is "und"efined then use the default locale.
80
    return locale == null || "und".equalsIgnoreCase( locale.toLanguageTag() )
81
      ? LOCALE_DEFAULT
82
      : locale;
83
  }
84
85
  public static ObservableList<String> localeListProperty() {
86
    return listProperty( sLocales.keySet() );
87
  }
88
89
  /**
90
   * Performs an O(n) search through the given map to find the key that is
91
   * mapped to the given value. A bi-directional map would be faster, but
92
   * also introduces additional dependencies. This doesn't need to be fast
93
   * because it happens once, at start up, and there aren't a lot of values.
94
   *
95
   * @param map   The map containing a key to find based on a value.
96
   * @param value The value to find within the map.
97
   * @param <K>   The type of key associated with a value.
98
   * @param <V>   The type of value associated with a key.
99
   * @return The key that corresponds to the given value, or {@code null} if
100
   * the key is not found.
101
   */
102
  @SuppressWarnings( "SameParameterValue" )
103
  private static <K, V> K getKey( final Map<K, V> map, final V value ) {
104
    for( final var entry : map.entrySet() ) {
105
      if( Objects.equals( value, entry.getValue() ) ) {
106
        return entry.getKey();
107
      }
108
    }
109
110
    return null;
111
  }
112
}
1113
A src/main/java/com/keenwrite/preferences/LocaleScripts.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.preferences;
3
4
import java.util.Collections;
5
import java.util.HashMap;
6
import java.util.Locale;
7
import java.util.Map;
8
9
import static java.util.Arrays.asList;
10
11
/**
12
 * Responsible for adding an ISO 15924 alpha-4 script code to {@link Locale}
13
 * instances. This allows all {@link Locale} objects to produce language tags
14
 * using the same format.
15
 */
16
public final class LocaleScripts {
17
  /**
18
   * ISO 15924 alpha-4 script code to represent Latin scripts.
19
   */
20
  private static final String SCRIPT_LATIN = "Latn";
21
22
  /**
23
   * This value is returned when a script hasn't been mapped for an instance of
24
   * {@link Locale}.
25
   */
26
  private static final Map<String, String> SCRIPT_DEFAULT = m( SCRIPT_LATIN );
27
28
  private static final Map<String, Map<String, String>> SCRIPTS =
29
    new HashMap<>();
30
31
  static {
32
    put( "en", m( "Latn" ) );
33
    put( "jp", m( "Jpan" ) );
34
    put( "ko", m( "Kore" ) );
35
    put( "zh", m( "Hant" ), m( "Hans", "CN", "MN", "MY", "SG" ) );
36
  }
37
38
  /**
39
   * Adds a script to a given {@link Locale} object. If the given {@link Locale}
40
   * already has a script, then it is returned unchanged.
41
   *
42
   * @param locale The {@link Locale} to update with its associated script.
43
   * @return The given {@link Locale} with a script included.
44
   */
45
  public static Locale withScript( Locale locale ) {
46
    assert locale != null;
47
48
    final var script = locale.getScript();
49
50
    if( script == null || script.isBlank() ) {
51
      final var builder = new Locale.Builder();
52
      builder.setLocale( locale );
53
      builder.setScript( getScript( locale ) );
54
      locale = builder.build();
55
    }
56
57
    return locale;
58
  }
59
60
  @SafeVarargs
61
  private static void put(
62
    final String language, final Map<String, String>... scripts ) {
63
    final var merged = new HashMap<String, String>();
64
    asList( scripts ).forEach( merged::putAll );
65
    SCRIPTS.put( language, merged );
66
  }
67
68
  /**
69
   * Returns the ISO 15924 alpha-4 script code for the given {@link Locale}.
70
   *
71
   * @param locale Language and country are used to find the script code.
72
   * @return The ISO code for the given locale, or {@link #SCRIPT_LATIN} if
73
   * no code has been mapped yet.
74
   */
75
  private static String getScript( final Locale locale ) {
76
    return SCRIPTS.getOrDefault( locale.getLanguage(), SCRIPT_DEFAULT )
77
                  .getOrDefault( locale.getCountry(), SCRIPT_LATIN );
78
  }
79
80
  /**
81
   * Helper method to instantiate a new {@link Map} having all keys referencing
82
   * the same value.
83
   *
84
   * @param v The value to associate with each key.
85
   * @param k The keys to associate with the given value.
86
   * @return A new {@link Map} with all keys referencing the same value.
87
   */
88
  private static Map<String, String> m( final String v, final String... k ) {
89
    final var map = new HashMap<String, String>();
90
    asList( k ).forEach( ( key ) -> map.put( key, v ) );
91
    return Collections.unmodifiableMap( map );
92
  }
93
94
  /**
95
   * Helper method to instantiate a new {@link Map} having an empty key
96
   * referencing the given value. This provides a default value so that
97
   * an unmapped country code can return a valid script code.
98
   *
99
   * @param v The value to associate with an empty key.
100
   * @return A new {@link Map} with the empty key referencing the given value.
101
   */
102
  private static Map<String, String> m( final String v ) {
103
    return m( v, "" );
104
  }
105
}
1106
A src/main/java/com/keenwrite/preferences/PreferencesController.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.preferences;
13
4
import com.dlsc.formsfx.model.structure.StringField;
5
import com.dlsc.preferencesfx.PreferencesFx;
6
import com.dlsc.preferencesfx.
A src/main/java/com/keenwrite/preferences/SimpleFontControl.java
1
/* Copyright 2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.preferences;
13
4
import com.dlsc.formsfx.model.structure.StringField;
5
import com.dlsc.preferencesfx.formsfx.view.controls.SimpleControl;
6
import javafx.beans.propertconstants
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
A src/main/java/com/keenwrite/preferences/Workspace.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.preferences;
13
4
import com.keenwrite.constants.Constants;
5
import com.keenwrite.sigils.Tokens;
6
import javafx.application.Platform;
7
import javafx.beans.propertytrue
A src/main/java/com/keenwrite/preferences/WorkspaceKeys.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.preferences;
3
4
import static com.keenwrite.preferences.Key.key;
15
6
/**
7
 * Responsible for defining constants used throughout the application that
8
 * represent 
A src/main/java/com/keenwrite/preferences/XmlStorageHandler.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.preferences;
3
4
import com.dlsc.preferencesfx.PreferencesFx;
5
import com.dlsc.preferencesfx.util.StorageHandler;
6
import javafx.collections.ObservableList;
17
8
impfinal
A src/main/java/com/keenwrite/preview/ChainedReplacedElementFactory.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.preview;
3
4
import com.keenwrite.preferences.Workspace;
5
import com.keenwrite.ui.adapters.ReplacedElementAdapter;
6
import com.keenwrite.util.BoundedCache;
7
import org.w3c.dom.Element;
8
import org.xhtmlrenderer.extend.ReplacedElement;
9
import org.xhtmlrenderer.extend.ReplacedElementFactory;
10
import org.xhtmlrenderer.extend.UserAgentCallback;
11
import org.xhtmlrenderer.layout.LayoutContext;
12
import org.xhtmlrenderer.render.BlockBox;
13
import org.xhtmlrenderer.swing.ImageReplacedElement;
14
15
import java.awt.event.ComponentEvent;
16
import java.awt.event.ComponentListener;
17
import java.util.LinkedHashSet;
18
import java.util.Map;
19
import java.util.Set;
20
21
import static com.keenwrite.preferences.WorkspaceKeys.KEY_IMAGES_RESIZE;
22
import static com.keenwrite.preview.SvgReplacedElementFactory.HTML_IMAGE;
23
import static com.keenwrite.preview.SvgReplacedElementFactory.HTML_IMAGE_SRC;
24
import static com.keenwrite.processors.markdown.extensions.tex.TexNode.HTML_TEX;
25
import static java.util.Arrays.asList;
26
27
/**
28
 * Responsible for running one or more factories to perform post-processing on
29
 * the HTML document prior to displaying it.
30
 */
31
public final class ChainedReplacedElementFactory
32
  extends ReplacedElementAdapter implements ComponentListener {
33
  /**
34
   * Retain insertion order so that client classes can control the order that
35
   * factories are used to resolve images.
36
   */
37
  private final Set<ReplacedElementFactory> mFactories = new LinkedHashSet<>();
38
39
  /**
40
   * A bounded cache that removes the oldest image if the maximum number of
41
   * cached images has been reached. This constrains the number of images
42
   * loaded into memory.
43
   */
44
  private final Map<String, ReplacedElement> mCache = new BoundedCache<>( 150 );
45
46
  private final Workspace mWorkspace;
47
48
  public ChainedReplacedElementFactory(
49
    final Workspace workspace, final ReplacedElementFactory... factories ) {
50
    assert workspace != null;
51
    assert factories != null;
52
    assert factories.length > 0;
53
    mWorkspace = workspace;
54
    mFactories.addAll( asList( factories ) );
55
  }
56
57
  @Override
58
  public ReplacedElement createReplacedElement(
59
    final LayoutContext c,
60
    final BlockBox box,
61
    final UserAgentCallback uac,
62
    final int width,
63
    final int height ) {
64
    for( final var f : mFactories ) {
65
      final var e = box.getElement();
66
67
      // Exit early for super-speed.
68
      if( e == null ) {
69
        break;
70
      }
71
72
      // If the source image is cached, don't bother fetching. This optimization
73
      // avoids making multiple HTTP requests for the same URI.
74
      final var node = e.getNodeName();
75
      final var source = switch( node ) {
76
        case HTML_IMAGE -> e.getAttribute( HTML_IMAGE_SRC );
77
        case HTML_TEX -> e.getTextContent();
78
        default -> "";
79
      };
80
81
      // HTML <img> or <tex> elements without source data shall not pass.
82
      if( source.isBlank() ) {
83
        break;
84
      }
85
86
      final var replaced = mCache.computeIfAbsent(
87
        source, k -> {
88
          final var r = f.createReplacedElement( c, box, uac, width, height );
89
          return r instanceof final ImageReplacedElement ire
90
            ? new SmoothImageReplacedElement(
91
            ire.getImage(), box.getWidth(), -1 )
92
            : r;
93
        }
94
      );
95
96
      if( replaced != null ) {
97
        return replaced;
98
      }
99
    }
100
101
    return null;
102
  }
103
104
  @Override
105
  public void reset() {
106
    for( final var factory : mFactories ) {
107
      factory.reset();
108
    }
109
  }
110
111
  @Override
112
  public void remove( final Element element ) {
113
    for( final var factory : mFactories ) {
114
      factory.remove( element );
115
    }
116
  }
117
118
  public void addFactory( final ReplacedElementFactory factory ) {
119
    mFactories.add( factory );
120
  }
121
122
  public void clearCache() {
123
    mCache.clear();
124
  }
125
126
  @Override
127
  public void componentResized( final ComponentEvent e ) {
128
    if( mWorkspace.toBoolean( KEY_IMAGES_RESIZE ) ) {
129
      clearCache();
130
    }
131
  }
132
133
  @Override
134
  public void componentMoved( final ComponentEvent e ) { }
135
136
  @Override
137
  public void componentShown( final ComponentEvent e ) { }
1138
139
  @Override
140
  public void componentHidden( final ComponentEvent e ) { }
141
}
A src/main/java/com/keenwrite/preview/DomConverter.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.preview;
3
4
import org.jsoup.helper.W3CDom;
5
import org.jsoup.nodeOMImplementationx.xml.parsers.DocumentBuilder;
6
import javax.xml.parsers.DocumentBuilderFactory;events.StatusEvent.cluefinal class Domnew LinkedHashMap<>();
7
8
  static {
9
    LIGATURES.put( "ffi", "\uFB03" );
10
    LIGATURES.put( "ffl", "\uFB04" );
11
    LIGATURES.put( "ff", "\uFB00" );
12
    LIGATURES.put( "fi", "\uFB01" );
13
    LIGATURES.put( "fl", "\uFB02" );
14
  }
15
T
16
        if( !("pre) ) {
17
          // Calling getWholeText()final var textNode = (TextNode) node;
18
    }
19
  };
20
DocumentBuilderFactory DOCUMENT_FACTORY;
21
  private static DocumentBuilder DOCUMENT_BUILDER;
22
  private static DOMImplementation DOM_IMPL;
23
24
  static {
25
    DOCUMENT_FACTORY = DocumentBuilderFactory.newInstance();
26
    DOCUMENT_FACTORY.setNamespaceAware( true );
27
28
    try {
29
      DOCUMENT_BUILDER = DOCUMENT_FACTORY.newDocumentBuilder();
30
      DOM_IMPL = DOCUMENT_BUILDER.getDOMImplementation();
31
    } catch( final Exception ex ) {
32
      clue( ex );
33
    }
34
  }
35
36
  @Override
37
  public    assert DOCUMENT_BUILDER != null;
38
    assert DOM_IMPLOCUMENT_BUILDER.newDocument();
39
    final org.jsoup.nodeTypeDOM_IMPL}
140
A src/main/java/com/keenwrite/preview/HighQualityRenderingHints.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 initializing settings to produce high-quality image
12
 * transformations.
13
 */
14
@SuppressWarnings( "rawtypes" )
15
public class HighQualityRenderingHints {
16
  /**
17
   * Default hints for high-quality rendering that may be changed by
18
   * the system's rendering hints.
19
   */
20
  private static final Map<Object, Object> DEFAULT_HINTS = Map.of(
21
    KEY_ANTIALIASING, VALUE_ANTIALIAS_ON,
22
    KEY_ALPHA_INTERPOLATION, VALUE_ALPHA_INTERPOLATION_QUALITY,
23
    KEY_COLOR_RENDERING, VALUE_COLOR_RENDER_QUALITY,
24
    KEY_DITHERING, VALUE_DITHER_DISABLE,
25
    KEY_FRACTIONALMETRICS, VALUE_FRACTIONALMETRICS_ON,
26
    KEY_INTERPOLATION, VALUE_INTERPOLATION_BICUBIC,
27
    KEY_RENDERING, VALUE_RENDER_QUALITY,
28
    KEY_STROKE_CONTROL, VALUE_STROKE_PURE,
29
    KEY_TEXT_ANTIALIASING, VALUE_TEXT_ANTIALIAS_ON
30
  );
31
32
  /**
33
   * Shared hints for high-quality rendering.
34
   */
35
  static final Map<Object, Object> RENDERING_HINTS = new HashMap<>(
36
    DEFAULT_HINTS
37
  );
38
39
  static {
40
    final var toolkit = getDefaultToolkit();
41
    final var hints = toolkit.getDesktopProperty( "awt.font.desktophints" );
42
43
    if( hints instanceof final Map map ) {
44
      for( final var key : map.keySet() ) {
45
        final var hint = map.get( key );
46
        RENDERING_HINTS.put( key, hint );
47
      }
48
    }
49
  }
50
51
  /**
52
   * Defines a reusable constant, nothing more.
53
   */
54
  private HighQualityRenderingHints() {
55
  }
56
}
157
A src/main/java/com/keenwrite/preview/HtmlPanel.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.preview;
13
4
import com.keenwrite.ui.adapters.DocumentAdapter;
5
imporHyperlinkOpenEvent.fireHyperlinkOpenlink ) {
6
      try {
7
        final var uri = new URI( link );
8
fireHyperlinkOpenEvent( uri );uri
A src/main/java/com/keenwrite/preview/HtmlPreview.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.preview;
13
4
import com.keenwrite.events.ScrollLockEvent;
5
import com.keenwrite.preferences.LocaleProperty;
6
import com.kee= new
A src/main/java/com/keenwrite/preview/MathRenderer.java
1
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved.events.StatusEvent
A src/main/java/com/keenwrite/preview/SmoothImageReplacedElement.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.preview;
3
4
import com.keenwrite.preview.images.Lanczos3Filter;
5
import com.keenwrite.preview.images.ResampleOp;
6
import org.xhtmlrenderer.swing.ImageReplacedElement;
7
8
import java.awt.*;
9
import java.awt.image.BufferedImage;
10
11
/**
12
 * Responsible for scaling an image using a Lanczos-3 filter, typically for
13
 * down-sampling.
14
 */
15
public final class SmoothImageReplacedElement extends ImageReplacedElement {
16
  private final static Lanczos3Filter FILTER = new Lanczos3Filter();
17
18
  /**
19
   * Creates a high-quality rescaled version of the given image. The
20
   * aspect ratio is maintained if either width or height is less than 1.
21
   *
22
   * @param source An instance of {@link BufferedImage} to rescale.
23
   * @param width  Rescale the given image to this width (px).
24
   * @param height Rescale the given image to this height (px).
25
   */
26
  public SmoothImageReplacedElement(
27
    final Image source, final int width, final int height ) {
28
    super._image = rescale( source, width, height );
29
  }
30
31
  private BufferedImage rescale(
32
    final Image source, final int w, final int h ) {
33
    final var bi = (BufferedImage) source;
34
    final var dim = rescaleDimensions( bi, w, h );
35
36
    final var resampleOp = new ResampleOp( FILTER, dim.width, dim.height );
37
    return resampleOp.filter( bi, null );
38
  }
39
40
  private Dimension rescaleDimensions(
41
    final BufferedImage bi, final int width, final int height ) {
42
    final var oldW = bi.getWidth();
43
    final var oldH = bi.getHeight();
44
45
    int newW = width;
46
    int newH = height;
47
48
    if( newW <= 0 ) {
49
      newW = (int) (oldW * ((double) newH / oldH));
50
    }
51
52
    if( newH <= 0 ) {
53
      newH = (int) (oldH * ((double) newW / oldW));
54
    }
55
56
    return new Dimension( newW, newH );
57
  }
58
}
159
A src/main/java/com/keenwrite/preview/SvgRasterizer.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved.css.parser.Parser;
2
import org.w3c.css.sac.CSSExceptionpreview.HighQualityRenderingHints.RENDERING_HINTS<a href="https://issues.apache.org/jira/browse/BATIK-1112">Bug fix</a>class InkscapeCssParser extends Parser {
3
    public void parseStyleDeclaration( final String source )
4
      throws CSSException, IOException {
5
      super.parseStyleDeclaration(
6
        source.replaceAll( "-inkscape-font-specification:[^;\"]*;", "" )
7
      );
8
    }
9
  }
110
11
  static {
12
    setCSSParserClassName(
13
      InkscapeCssParser.class.getName()
14
    )
A src/main/java/com/keenwrite/preview/SvgReplacedElementFactory.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.preview;
13
4
import com.keenwrite.io.dapters.ReplacedElementAdapter;
5
import org.w3c.dom.Element;
6
import orgHttpFacade.httpGet.isUndefined()try( final var response = httpGet( uri mediaType = response.getMediaType();
7
              }mediaTypemediaType
A src/main/java/com/keenwrite/preview/images/AdvancedResizeOp.java
1
/*
2
 * Copyright 2013, Morten Nobel-Joergensen
3
 *
4
 * License: The BSD 3-Clause License
5
 * http://opensource.org/licenses/BSD-3-Clause
6
 */
7
package com.keenwrite.preview.images;
8
9
import java.awt.*;
10
import java.awt.geom.Point2D;
11
import java.awt.geom.Rectangle2D;
12
import java.awt.image.BufferedImage;
13
import java.awt.image.BufferedImageOp;
14
import java.awt.image.ColorModel;
15
16
/**
17
 * @author Morten Nobel-Joergensen
18
 */
19
public abstract class AdvancedResizeOp implements BufferedImageOp {
20
  private final ConstrainedDimension dimensionConstrain;
21
22
  public AdvancedResizeOp( ConstrainedDimension dimensionConstrain ) {
23
    this.dimensionConstrain = dimensionConstrain;
24
  }
25
26
  public final BufferedImage filter( BufferedImage src, BufferedImage dest ) {
27
    Dimension dstDimension = dimensionConstrain.getDimension(
28
      new Dimension( src.getWidth(), src.getHeight() ) );
29
    int dstWidth = dstDimension.width;
30
    int dstHeight = dstDimension.height;
31
32
    return doFilter( src, dest, dstWidth, dstHeight );
33
  }
34
35
  protected abstract BufferedImage doFilter(
36
    BufferedImage src, BufferedImage dest, int dstWidth, int dstHeight );
37
38
  @Override
39
  public final Rectangle2D getBounds2D( BufferedImage src ) {
40
    return new Rectangle( 0, 0, src.getWidth(), src.getHeight() );
41
  }
42
43
  @Override
44
  public final BufferedImage createCompatibleDestImage(
45
    BufferedImage src, ColorModel destCM ) {
46
    if( destCM == null ) {
47
      destCM = src.getColorModel();
48
    }
49
50
    return new BufferedImage(
51
      destCM,
52
      destCM.createCompatibleWritableRaster( src.getWidth(), src.getHeight() ),
53
      destCM.isAlphaPremultiplied(),
54
      null );
55
  }
56
57
  @Override
58
  public final Point2D getPoint2D( Point2D srcPt, Point2D dstPt ) {
59
    return (Point2D) srcPt.clone();
60
  }
61
62
  @Override
63
  public final RenderingHints getRenderingHints() {
64
    return null;
65
  }
66
}
167
A src/main/java/com/keenwrite/preview/images/ConstrainedDimension.java
1
/*
2
 * Copyright 2013, Morten Nobel-Joergensen
3
 *
4
 * License: The BSD 3-Clause License
5
 * http://opensource.org/licenses/BSD-3-Clause
6
 */
7
package com.keenwrite.preview.images;
8
9
import java.awt.*;
10
11
/**
12
 * This class let you create dimension constrains based on a actual image.
13
 */
14
public class ConstrainedDimension {
15
  private ConstrainedDimension() {
16
  }
17
18
  /**
19
   * Will always return a dimension with positive width and height;
20
   *
21
   * @param dimension of the unscaled image
22
   * @return the dimension of the scaled image
23
   */
24
  public Dimension getDimension( Dimension dimension ) {
25
    return dimension;
26
  }
27
28
  /**
29
   * Used when the destination size is fixed. This may not keep the image
30
   * aspect radio.
31
   *
32
   * @param width  destination dimension width
33
   * @param height destination dimension height
34
   * @return destination dimension (width x height)
35
   */
36
  public static ConstrainedDimension createAbsolutionDimension(
37
    final int width, final int height ) {
38
    assert width > 0 && height > 0 : "Dimensions must be positive integers";
39
    return new ConstrainedDimension() {
40
      public Dimension getDimension( Dimension dimension ) {
41
        return new Dimension( width, height );
42
      }
43
    };
44
  }
45
}
146
A src/main/java/com/keenwrite/preview/images/ImageUtils.java
1
/*
2
 * Copyright 2013, Morten Nobel-Joergensen
3
 *
4
 * License: The BSD 3-Clause License
5
 * http://opensource.org/licenses/BSD-3-Clause
6
 */
7
package com.keenwrite.preview.images;
8
9
import java.awt.*;
10
import java.awt.image.BufferedImage;
11
import java.awt.image.Raster;
12
import java.awt.image.WritableRaster;
13
14
import static java.awt.image.BufferedImage.*;
15
16
/**
17
 * @author Heinz Doerr
18
 * @author Morten Nobel-Joergensen
19
 */
20
public final class ImageUtils {
21
  @SuppressWarnings( "DuplicateBranchesInSwitch" )
22
  static int nrChannels( final BufferedImage img ) {
23
    return switch( img.getType() ) {
24
      case TYPE_3BYTE_BGR -> 3;
25
      case TYPE_4BYTE_ABGR -> 4;
26
      case TYPE_BYTE_GRAY -> 1;
27
      case TYPE_INT_BGR -> 3;
28
      case TYPE_INT_ARGB -> 4;
29
      case TYPE_INT_RGB -> 3;
30
      case TYPE_CUSTOM -> 4;
31
      case TYPE_4BYTE_ABGR_PRE -> 4;
32
      case TYPE_INT_ARGB_PRE -> 4;
33
      case TYPE_USHORT_555_RGB -> 3;
34
      case TYPE_USHORT_565_RGB -> 3;
35
      case TYPE_USHORT_GRAY -> 1;
36
      default -> 0;
37
    };
38
  }
39
40
  /**
41
   * returns one row (height == 1) of byte packed image data in BGR or AGBR form
42
   *
43
   * @param temp must be either null or a array with length of w*h
44
   */
45
  static void getPixelsBGR(
46
    BufferedImage img, int y, int w, byte[] array, int[] temp ) {
47
    final int x = 0;
48
    final int h = 1;
49
50
    assert array.length == temp.length * nrChannels( img );
51
    assert (temp.length == w);
52
53
    final Raster raster;
54
    switch( img.getType() ) {
55
      case TYPE_3BYTE_BGR, TYPE_4BYTE_ABGR,
56
        TYPE_4BYTE_ABGR_PRE, TYPE_BYTE_GRAY -> {
57
        raster = img.getRaster();
58
        //int ttype= raster.getTransferType();
59
        raster.getDataElements( x, y, w, h, array );
60
      }
61
      case TYPE_INT_BGR -> {
62
        raster = img.getRaster();
63
        raster.getDataElements( x, y, w, h, temp );
64
        ints2bytes( temp, array, 0, 1, 2 );  // bgr -->  bgr
65
      }
66
      case TYPE_INT_RGB -> {
67
        raster = img.getRaster();
68
        raster.getDataElements( x, y, w, h, temp );
69
        ints2bytes( temp, array, 2, 1, 0 );  // rgb -->  bgr
70
      }
71
      case TYPE_INT_ARGB, TYPE_INT_ARGB_PRE -> {
72
        raster = img.getRaster();
73
        raster.getDataElements( x, y, w, h, temp );
74
        ints2bytes( temp, array, 2, 1, 0, 3 );  // argb -->  abgr
75
      }
76
      case TYPE_CUSTOM -> {
77
        // loader, but else ???
78
        img.getRGB( x, y, w, h, temp, 0, w );
79
        ints2bytes( temp, array, 2, 1, 0, 3 );  // argb -->  abgr
80
      }
81
      default -> {
82
        img.getRGB( x, y, w, h, temp, 0, w );
83
        ints2bytes( temp, array, 2, 1, 0 );  // rgb -->  bgr
84
      }
85
    }
86
  }
87
88
  /**
89
   * converts and copies byte packed  BGR or ABGR into the img buffer,
90
   * the img type may vary (e.g. RGB or BGR, int or byte packed)
91
   * but the number of components (w/o alpha, w alpha, gray) must match
92
   * <p>
93
   * does not unmange the image for all (A)RGN and (A)BGR and gray imaged
94
   */
95
  public static void setBGRPixels( byte[] bgrPixels, BufferedImage img, int x,
96
                                   int y, int w, int h ) {
97
    int imageType = img.getType();
98
    WritableRaster raster = img.getRaster();
99
100
    if( imageType == TYPE_3BYTE_BGR ||
101
      imageType == TYPE_4BYTE_ABGR ||
102
      imageType == TYPE_4BYTE_ABGR_PRE ||
103
      imageType == TYPE_BYTE_GRAY ) {
104
      raster.setDataElements( x, y, w, h, bgrPixels );
105
    }
106
    else {
107
      int[] pixels;
108
      if( imageType == TYPE_INT_BGR ) {
109
        pixels = bytes2int( bgrPixels, 2, 1, 0 );  // bgr -->  bgr
110
      }
111
      else if( imageType == TYPE_INT_ARGB ||
112
        imageType == TYPE_INT_ARGB_PRE ) {
113
        pixels = bytes2int( bgrPixels, 3, 0, 1, 2 );  // abgr -->  argb
114
      }
115
      else {
116
        pixels = bytes2int( bgrPixels, 0, 1, 2 );  // bgr -->  rgb
117
      }
118
      if( w == 0 || h == 0 ) {
119
        return;
120
      }
121
      else if( pixels.length < w * h ) {
122
        throw new IllegalArgumentException( "pixels array must have a length" + " >= w*h" );
123
      }
124
      if( imageType == TYPE_INT_ARGB ||
125
        imageType == TYPE_INT_RGB ||
126
        imageType == TYPE_INT_ARGB_PRE ||
127
        imageType == TYPE_INT_BGR ) {
128
        raster.setDataElements( x, y, w, h, pixels );
129
      }
130
      else {
131
        // Unmanages the image
132
        img.setRGB( x, y, w, h, pixels, 0, w );
133
      }
134
    }
135
  }
136
137
  public static void ints2bytes( int[] in, byte[] out, int index1, int index2,
138
                                 int index3 ) {
139
    for( int i = 0; i < in.length; i++ ) {
140
      int index = i * 3;
141
      int value = in[ i ];
142
      out[ index + index1 ] = (byte) value;
143
      value = value >> 8;
144
      out[ index + index2 ] = (byte) value;
145
      value = value >> 8;
146
      out[ index + index3 ] = (byte) value;
147
    }
148
  }
149
150
  public static void ints2bytes( int[] in, byte[] out, int index1, int index2,
151
                                 int index3, int index4 ) {
152
    for( int i = 0; i < in.length; i++ ) {
153
      int index = i * 4;
154
      int value = in[ i ];
155
      out[ index + index1 ] = (byte) value;
156
      value = value >> 8;
157
      out[ index + index2 ] = (byte) value;
158
      value = value >> 8;
159
      out[ index + index3 ] = (byte) value;
160
      value = value >> 8;
161
      out[ index + index4 ] = (byte) value;
162
    }
163
  }
164
165
  public static int[] bytes2int( byte[] in, int index1, int index2,
166
                                 int index3 ) {
167
    int[] out = new int[ in.length / 3 ];
168
    for( int i = 0; i < out.length; i++ ) {
169
      int index = i * 3;
170
      int b1 = (in[ index + index1 ] & 0xff) << 16;
171
      int b2 = (in[ index + index2 ] & 0xff) << 8;
172
      int b3 = in[ index + index3 ] & 0xff;
173
      out[ i ] = b1 | b2 | b3;
174
    }
175
    return out;
176
  }
177
178
  public static int[] bytes2int( byte[] in, int index1, int index2, int index3,
179
                                 int index4 ) {
180
    int[] out = new int[ in.length / 4 ];
181
    for( int i = 0; i < out.length; i++ ) {
182
      int index = i * 4;
183
      int b1 = (in[ index + index1 ] & 0xff) << 24;
184
      int b2 = (in[ index + index2 ] & 0xff) << 16;
185
      int b3 = (in[ index + index3 ] & 0xff) << 8;
186
      int b4 = in[ index + index4 ] & 0xff;
187
      out[ i ] = b1 | b2 | b3 | b4;
188
    }
189
    return out;
190
  }
191
192
  public static BufferedImage convert( BufferedImage src, int bufImgType ) {
193
    BufferedImage img = new BufferedImage( src.getWidth(),
194
                                           src.getHeight(),
195
                                           bufImgType );
196
    Graphics2D g2d = img.createGraphics();
197
    g2d.drawImage( src, 0, 0, null );
198
    g2d.dispose();
199
    return img;
200
  }
201
}
1202
A src/main/java/com/keenwrite/preview/images/Lanczos3.java
1
package com.keenwrite.preview.images;
2
3
import java.awt.image.BufferedImage;
4
5
/**
6
 * Unused. Needs to extract image data from {@link BufferedImage} and create
7
 * down-sampled version.
8
 */
9
public class Lanczos3 {
10
  static double sinc( double x ) {
11
    x *= Math.PI;
12
13
    if( (x < 0.01f) && (x > -0.01f) ) {
14
      return 1.0f + x * x * (-1.0f / 6.0f + x * x * 1.0f / 120.0f);
15
    }
16
17
    return Math.sin( x ) / x;
18
  }
19
20
  static float clip( double t ) {
21
    final float eps = .0000125f;
22
23
    if( Math.abs( t ) < eps ) { return 0.0f; }
24
25
    return (float) t;
26
  }
27
28
  static float lancos( float t ) {
29
    if( t < 0.0f ) { t = -t; }
30
31
    if( t < 3.0f ) { return clip( sinc( t ) * sinc( t / 3.0f ) ); }
32
    else { return (0.0f); }
33
  }
34
35
  static float lancos3_resample_x(
36
    int[][] arr, int src_w, int src_h, int y, int x, float xscale ) {
37
    float s = 0;
38
    float coef_sum = 0.0f;
39
    float coef;
40
    float pix;
41
    int i;
42
43
    int l, r;
44
    float c;
45
    float hw;
46
47
    // For the reduction of the situation hw is equivalent to expanding the
48
    // number of pixels in the field, if you do not do this, the final
49
    // reduction of the image effect is not much different from the recent
50
    // field interpolation method, the effect is equivalent to the first
51
    // low-pass filtering, and then interpolate
52
    if( xscale > 1.0f ) { hw = 3.0f; }
53
    else { hw = 3.0f / xscale; }
54
55
    c = (float) x / xscale;
56
    l = (int) Math.floor( c - hw );
57
    r = (int) Math.ceil( c + hw );
58
59
    if( y < 0 ) { y = 0; }
60
    if( y >= src_h ) { y = src_h - 1; }
61
    if( xscale > 1.0f ) { xscale = 1.0f; }
62
    for( i = l; i <= r; i++ ) {
63
      x = Math.max( i, 0 );
64
      if( i >= src_w ) { x = src_w - 1; }
65
      pix = arr[ y ][ x ];
66
      coef = lancos( (c - i) * xscale );
67
      s += pix * coef;
68
      coef_sum += coef;
69
    }
70
    s /= coef_sum;
71
    return s;
72
  }
73
74
  static class uint8_2d {
75
    int[][] arr;
76
    int rows;
77
    int cols;
78
79
    public uint8_2d( final int h1, final int w1 ) {
80
      arr = new int[ h1 ][ w1 ];
81
      rows = h1;
82
      cols = w1;
83
    }
84
  }
85
86
  void img_resize_using_lancos3( uint8_2d src, uint8_2d dst ) {
87
    if( src == null || dst == null ) { return; }
88
89
    int src_rows, src_cols;
90
    int dst_rows, dst_cols;
91
    int i, j;
92
    int[][] src_arr;
93
    int[][] dst_arr;
94
    float xratio;
95
    float yratio;
96
    int val;
97
    int k;
98
    float hw;
99
100
    src_arr = src.arr;
101
    dst_arr = dst.arr;
102
    src_rows = src.rows;
103
    src_cols = src.cols;
104
    dst_rows = dst.rows;
105
    dst_cols = dst.cols;
106
107
    xratio = (float) (dst_cols) / (float) src_cols;
108
    yratio = (float) (dst_rows) / (float) src_rows;
109
110
    float scale;
111
112
    if( yratio > 1.0f ) {
113
      hw = 3.0f;
114
      scale = 1.0f;
115
    }
116
    else {
117
      hw = 3.0f / yratio;
118
      scale = yratio;
119
    }
120
121
    for( i = 0; i < dst_rows; i++ ) {
122
      for( j = 0; j < dst_cols; j++ ) {
123
        int t, b;
124
        float c;
125
126
        float s = 0;
127
        float coef_sum = 0.0f;
128
        float coef;
129
        float pix;
130
131
        c = (float) i / yratio;
132
        t = (int) Math.floor( c - hw );
133
        b = (int) Math.ceil( c + hw );
134
        // Interpolate in the x direction first, then interpolate in the y
135
        // direction.
136
        for( k = t; k <= b; k++ ) {
137
          pix = lancos3_resample_x( src_arr, src_cols, src_rows, k, j, xratio );
138
          coef = lancos( (c - k) * scale );
139
          coef_sum += coef;
140
          pix *= coef;
141
          s += pix;
142
        }
143
        val = (int) (s / coef_sum);
144
        if( val < 0 ) { val = 0; }
145
        if( val > 255 ) { val = 255; }
146
        dst_arr[ i ][ j ] = val;
147
      }
148
    }
149
  }
150
151
  BufferedImage test_lancos3_resize( BufferedImage img, float factor ) {
152
    assert img != null;
153
154
    uint8_2d r = null;
155
    uint8_2d g = null;
156
    uint8_2d b = null;
157
158
    BufferedImage out = null;
159
    // TODO: Split buffered image into RGB components.
160
    //split_img_data( img, r, g, b );
161
162
    int w, h;
163
    int w1, h1;
164
    w = img.getWidth();
165
    h = img.getHeight();
166
167
    // TODO: Maintain aspect ratio.
168
    w1 = (int) (factor * w);
169
    h1 = (int) (factor * h);
170
171
    uint8_2d r1 = new uint8_2d( h1, w1 );
172
    uint8_2d g1 = new uint8_2d( h1, w1 );
173
    uint8_2d b1 = new uint8_2d( h1, w1 );
174
175
    img_resize_using_lancos3( r, r1 );
176
    img_resize_using_lancos3( g, g1 );
177
    img_resize_using_lancos3( b, b1 );
178
179
    // TODO: Combine rescaled image into RGB components.
180
    //merge_img_data( r1, g1, b1, out);
181
182
    return out;
183
  }
184
}
1185
A src/main/java/com/keenwrite/preview/images/Lanczos3Filter.java
1
/*
2
 * Copyright 2013, Morten Nobel-Joergensen
3
 *
4
 * License: The BSD 3-Clause License
5
 * http://opensource.org/licenses/BSD-3-Clause
6
 */
7
package com.keenwrite.preview.images;
8
9
public final class Lanczos3Filter implements ResampleFilter {
10
  private final static float PI_FLOAT = (float) Math.PI;
11
12
  private float sincModified( float value ) {
13
    return (float) Math.sin( value ) / value;
14
  }
15
16
  public final float apply( float value ) {
17
    if( value == 0 ) {
18
      return 1.0f;
19
    }
20
21
    if( value < 0.0f ) {
22
      value = -value;
23
    }
24
25
    if( value < 3.0f ) {
26
      value *= PI_FLOAT;
27
      return sincModified( value ) * sincModified( value / 3.0f );
28
    }
29
30
    return 0.0f;
31
  }
32
33
  public float getSamplingRadius() {
34
    return 3.0f;
35
  }
36
}
137
A src/main/java/com/keenwrite/preview/images/ResampleFilter.java
1
/*
2
 * Copyright 2013, Morten Nobel-Joergensen
3
 *
4
 * License: The BSD 3-Clause License
5
 * http://opensource.org/licenses/BSD-3-Clause
6
 */
7
package com.keenwrite.preview.images;
8
9
public interface ResampleFilter {
10
  float getSamplingRadius();
11
12
  float apply(float v);
13
}
114
A src/main/java/com/keenwrite/preview/images/ResampleOp.java
1
/*
2
 * Copyright 2013, Morten Nobel-Joergensen
3
 *
4
 * License: The BSD 3-Clause License
5
 * http://opensource.org/licenses/BSD-3-Clause
6
 */
7
package com.keenwrite.preview.images;
8
9
import java.awt.image.BufferedImage;
10
import java.util.concurrent.atomic.AtomicInteger;
11
12
import static com.keenwrite.preview.images.ConstrainedDimension.createAbsolutionDimension;
13
import static java.awt.image.BufferedImage.*;
14
import static java.awt.image.DataBuffer.TYPE_USHORT;
15
import static java.lang.Runtime.getRuntime;
16
import static java.lang.String.format;
17
import static java.lang.Thread.currentThread;
18
19
/**
20
 * Based on <a href="http://schmidt.devlib.org/jiu/">Java Image Util</a>.
21
 * <p>
22
 * Note that the filter method is not thread-safe.
23
 * </p>
24
 *
25
 * @author Morten Nobel-Joergensen
26
 * @author Heinz Doerr
27
 */
28
public class ResampleOp extends AdvancedResizeOp {
29
  private static final int MAX_CHANNEL_VALUE = 255;
30
31
  private int nrChannels;
32
  private int srcWidth;
33
  private int srcHeight;
34
  private int dstWidth;
35
  private int dstHeight;
36
37
  static class SubSamplingData {
38
    // individual - per row or per column - nr of contributions
39
    private final int[] arrN;
40
    // 2Dim: [wid or hei][contrib]
41
    private final int[] arrPixel;
42
    // 2Dim: [wid or hei][contrib]
43
    private final float[] arrWeight;
44
    // the primary index length for the 2Dim arrays : arrPixel and arrWeight
45
    private final int numContributors;
46
47
    private SubSamplingData( int[] arrN, int[] arrPixel, float[] arrWeight,
48
                             int numContributors ) {
49
      this.arrN = arrN;
50
      this.arrPixel = arrPixel;
51
      this.arrWeight = arrWeight;
52
      this.numContributors = numContributors;
53
    }
54
55
    public int getNumContributors() {
56
      return numContributors;
57
    }
58
59
    public int[] getArrN() {
60
      return arrN;
61
    }
62
63
    public float[] getArrWeight() {
64
      return arrWeight;
65
    }
66
  }
67
68
  private SubSamplingData horizontalSubsamplingData;
69
  private SubSamplingData verticalSubsamplingData;
70
71
  private final int threadCount = getRuntime().availableProcessors();
72
  private final AtomicInteger multipleInvocationLock = new AtomicInteger();
73
  private final ResampleFilter mFilter;
74
75
  public ResampleOp(
76
    final ResampleFilter filter, final int destWidth, final int destHeight ) {
77
    this( filter,
78
          createAbsolutionDimension( destWidth, destHeight ) );
79
  }
80
81
  public ResampleOp(
82
    final ResampleFilter filter, ConstrainedDimension dimensionConstrain ) {
83
    super( dimensionConstrain );
84
    mFilter = filter;
85
  }
86
87
  public BufferedImage doFilter(
88
    BufferedImage srcImg, BufferedImage dest, int dstWidth, int dstHeight ) {
89
    this.dstWidth = dstWidth;
90
    this.dstHeight = dstHeight;
91
92
    if( dstWidth < 3 || dstHeight < 3 ) {
93
      throw new IllegalArgumentException( "Target must be at least 3x3." );
94
    }
95
96
    assert multipleInvocationLock.incrementAndGet() == 1 :
97
      "Multiple concurrent invocations detected";
98
99
    final var srcType = srcImg.getType();
100
101
    if( srcType == TYPE_BYTE_BINARY ||
102
      srcType == TYPE_BYTE_INDEXED ||
103
      srcType == TYPE_CUSTOM ) {
104
      srcImg = ImageUtils.convert(
105
        srcImg,
106
        srcImg.getColorModel().hasAlpha() ? TYPE_4BYTE_ABGR : TYPE_3BYTE_BGR );
107
    }
108
109
    this.nrChannels = ImageUtils.nrChannels( srcImg );
110
    assert nrChannels > 0;
111
    this.srcWidth = srcImg.getWidth();
112
    this.srcHeight = srcImg.getHeight();
113
114
    byte[][] workPixels = new byte[ srcHeight ][ dstWidth * nrChannels ];
115
116
    // Pre-calculate  sub-sampling
117
    horizontalSubsamplingData = createSubSampling(
118
      mFilter, srcWidth, dstWidth );
119
    verticalSubsamplingData = createSubSampling(
120
      mFilter, srcHeight, dstHeight );
121
122
    final BufferedImage scrImgCopy = srcImg;
123
    final byte[][] workPixelsCopy = workPixels;
124
    final Thread[] threads = new Thread[ threadCount - 1 ];
125
126
    for( int i = 1; i < threadCount; i++ ) {
127
      final int finalI = i;
128
      threads[ i - 1 ] = new Thread( () -> horizontallyFromSrcToWork(
129
        scrImgCopy, workPixelsCopy, finalI, threadCount ) );
130
      threads[ i - 1 ].start();
131
    }
132
133
    horizontallyFromSrcToWork( scrImgCopy, workPixelsCopy, 0, threadCount );
134
    waitForAllThreads( threads );
135
136
    byte[] outPixels = new byte[ dstWidth * dstHeight * nrChannels ];
137
138
    // --------------------------------------------------
139
    // Apply filter to sample vertically from Work to Dst
140
    // --------------------------------------------------
141
    final byte[] outPixelsCopy = outPixels;
142
    for( int i = 1; i < threadCount; i++ ) {
143
      final int finalI = i;
144
      threads[ i - 1 ] = new Thread( () -> verticalFromWorkToDst(
145
        workPixelsCopy, outPixelsCopy, finalI, threadCount ) );
146
      threads[ i - 1 ].start();
147
    }
148
    verticalFromWorkToDst( workPixelsCopy, outPixelsCopy, 0, threadCount );
149
    waitForAllThreads( threads );
150
151
    //noinspection UnusedAssignment
152
    workPixels = null; // free memory
153
    final BufferedImage out;
154
    if( dest != null && dstWidth == dest.getWidth() && dstHeight == dest.getHeight() ) {
155
      out = dest;
156
      int nrDestChannels = ImageUtils.nrChannels( dest );
157
      if( nrDestChannels != nrChannels ) {
158
        final var errorMgs = format(
159
          "Destination image must be compatible width source image. Source " +
160
            "image had %d channels destination image had %d channels",
161
          nrChannels, nrDestChannels );
162
        throw new RuntimeException( errorMgs );
163
      }
164
    }
165
    else {
166
      out = new BufferedImage(
167
        dstWidth, dstHeight, getResultBufferedImageType( srcImg ) );
168
    }
169
170
    ImageUtils.setBGRPixels( outPixels, out, 0, 0, dstWidth, dstHeight );
171
172
    assert multipleInvocationLock.decrementAndGet() == 0 : "Multiple " +
173
      "concurrent invocations detected";
174
175
    return out;
176
  }
177
178
  private void waitForAllThreads( final Thread[] threads ) {
179
    try {
180
      for( final Thread thread : threads ) {
181
        thread.join( Long.MAX_VALUE );
182
      }
183
    } catch( final InterruptedException e ) {
184
      currentThread().interrupt();
185
      throw new RuntimeException( e );
186
    }
187
  }
188
189
  static SubSamplingData createSubSampling(
190
    ResampleFilter filter, int srcSize, int dstSize ) {
191
    final float scale = (float) dstSize / (float) srcSize;
192
    final int[] arrN = new int[ dstSize ];
193
    final int numContributors;
194
    final float[] arrWeight;
195
    final int[] arrPixel;
196
197
    final float fwidth = filter.getSamplingRadius();
198
199
    float centerOffset = 0.5f / scale;
200
201
    if( scale < 1.0f ) {
202
      final float width = fwidth / scale;
203
      // Add 2 to be safe with the ceiling
204
      numContributors = (int) (width * 2.0f + 2);
205
      arrWeight = new float[ dstSize * numContributors ];
206
      arrPixel = new int[ dstSize * numContributors ];
207
208
      final float fNormFac = (float) (1f / (Math.ceil( width ) / fwidth));
209
210
      for( int i = 0; i < dstSize; i++ ) {
211
        final int subindex = i * numContributors;
212
        float center = i / scale + centerOffset;
213
        int left = (int) Math.floor( center - width );
214
        int right = (int) Math.ceil( center + width );
215
        for( int j = left; j <= right; j++ ) {
216
          float weight;
217
          weight = filter.apply( (center - j) * fNormFac );
218
219
          if( weight == 0.0f ) {
220
            continue;
221
          }
222
          int n;
223
          if( j < 0 ) {
224
            n = -j;
225
          }
226
          else if( j >= srcSize ) {
227
            n = srcSize - j + srcSize - 1;
228
          }
229
          else {
230
            n = j;
231
          }
232
          int k = arrN[ i ];
233
          //assert k == j-left:String.format("%s = %s %s", k,j,left);
234
          arrN[ i ]++;
235
          if( n < 0 || n >= srcSize ) {
236
            weight = 0.0f;// Flag that cell should not be used
237
          }
238
          arrPixel[ subindex + k ] = n;
239
          arrWeight[ subindex + k ] = weight;
240
        }
241
        // normalize the filter's weight's so the sum equals to 1.0, very
242
        // important for avoiding box type of artifacts
243
        final int max = arrN[ i ];
244
        float tot = 0;
245
        for( int k = 0; k < max; k++ ) { tot += arrWeight[ subindex + k ]; }
246
        if( tot != 0f ) { // 0 should never happen except bug in filter
247
          for( int k = 0; k < max; k++ ) { arrWeight[ subindex + k ] /= tot; }
248
        }
249
      }
250
    }
251
    else {
252
      // super-sampling
253
      // Scales from smaller to bigger height
254
      numContributors = (int) (fwidth * 2.0f + 1);
255
      arrWeight = new float[ dstSize * numContributors ];
256
      arrPixel = new int[ dstSize * numContributors ];
257
      //
258
      for( int i = 0; i < dstSize; i++ ) {
259
        final int subindex = i * numContributors;
260
        float center = i / scale + centerOffset;
261
        int left = (int) Math.floor( center - fwidth );
262
        int right = (int) Math.ceil( center + fwidth );
263
        for( int j = left; j <= right; j++ ) {
264
          float weight = filter.apply( center - j );
265
          if( weight == 0.0f ) {
266
            continue;
267
          }
268
          int n;
269
          if( j < 0 ) {
270
            n = -j;
271
          }
272
          else if( j >= srcSize ) {
273
            n = srcSize - j + srcSize - 1;
274
          }
275
          else {
276
            n = j;
277
          }
278
          int k = arrN[ i ];
279
          arrN[ i ]++;
280
          if( n < 0 || n >= srcSize ) {
281
            weight = 0.0f;// Flag that cell should not be used
282
          }
283
          arrPixel[ subindex + k ] = n;
284
          arrWeight[ subindex + k ] = weight;
285
        }
286
        // normalize the filter's weight's so the sum equals to 1.0, very
287
        // important for avoiding box type of artifacts
288
        final int max = arrN[ i ];
289
        float tot = 0;
290
        for( int k = 0; k < max; k++ ) { tot += arrWeight[ subindex + k ]; }
291
        assert tot != 0 : "should never happen except bug in filter";
292
        if( tot != 0f ) {
293
          for( int k = 0; k < max; k++ ) { arrWeight[ subindex + k ] /= tot; }
294
        }
295
      }
296
    }
297
    return new SubSamplingData( arrN, arrPixel, arrWeight, numContributors );
298
  }
299
300
  private void verticalFromWorkToDst( byte[][] workPixels, byte[] outPixels,
301
                                      int start, int delta ) {
302
    if( nrChannels == 1 ) {
303
      verticalFromWorkToDstGray(
304
        workPixels, outPixels, start, threadCount );
305
      return;
306
    }
307
    boolean useChannel3 = nrChannels > 3;
308
    for( int x = start; x < dstWidth; x += delta ) {
309
      final int xLocation = x * nrChannels;
310
      for( int y = dstHeight - 1; y >= 0; y-- ) {
311
        final int yTimesNumContributors =
312
          y * verticalSubsamplingData.numContributors;
313
        final int max = verticalSubsamplingData.arrN[ y ];
314
        final int sampleLocation = (y * dstWidth + x) * nrChannels;
315
316
        float sample0 = 0.0f;
317
        float sample1 = 0.0f;
318
        float sample2 = 0.0f;
319
        float sample3 = 0.0f;
320
        int index = yTimesNumContributors;
321
        for( int j = max - 1; j >= 0; j-- ) {
322
          int valueLocation = verticalSubsamplingData.arrPixel[ index ];
323
          float arrWeight = verticalSubsamplingData.arrWeight[ index ];
324
          sample0 += (workPixels[ valueLocation ][ xLocation ] & 0xff) * arrWeight;
325
          sample1 += (workPixels[ valueLocation ][ xLocation + 1 ] & 0xff) * arrWeight;
326
          sample2 += (workPixels[ valueLocation ][ xLocation + 2 ] & 0xff) * arrWeight;
327
          if( useChannel3 ) {
328
            sample3 += (workPixels[ valueLocation ][ xLocation + 3 ] & 0xff) * arrWeight;
329
          }
330
331
          index++;
332
        }
333
334
        outPixels[ sampleLocation ] = toByte( sample0 );
335
        outPixels[ sampleLocation + 1 ] = toByte( sample1 );
336
        outPixels[ sampleLocation + 2 ] = toByte( sample2 );
337
338
        if( useChannel3 ) {
339
          outPixels[ sampleLocation + 3 ] = toByte( sample3 );
340
        }
341
      }
342
    }
343
  }
344
345
  private void verticalFromWorkToDstGray(
346
    byte[][] workPixels, byte[] outPixels, int start, int delta ) {
347
    for( int x = start; x < dstWidth; x += delta ) {
348
      for( int y = dstHeight - 1; y >= 0; y-- ) {
349
        final int yTimesNumContributors =
350
          y * verticalSubsamplingData.numContributors;
351
        final int max = verticalSubsamplingData.arrN[ y ];
352
        final int sampleLocation = y * dstWidth + x;
353
        float sample0 = 0.0f;
354
        int index = yTimesNumContributors;
355
356
        for( int j = max - 1; j >= 0; j-- ) {
357
          int valueLocation = verticalSubsamplingData.arrPixel[ index ];
358
          float arrWeight = verticalSubsamplingData.arrWeight[ index ];
359
          sample0 += (workPixels[ valueLocation ][ x ] & 0xff) * arrWeight;
360
361
          index++;
362
        }
363
364
        outPixels[ sampleLocation ] = toByte( sample0 );
365
      }
366
    }
367
  }
368
369
  /**
370
   * Apply filter to sample horizontally from Src to Work
371
   */
372
  private void horizontallyFromSrcToWork(
373
    BufferedImage srcImg, byte[][] workPixels, int start, int delta ) {
374
    if( nrChannels == 1 ) {
375
      horizontallyFromSrcToWorkGray( srcImg, workPixels, start, delta );
376
      return;
377
    }
378
379
    // Used if we work on int based bitmaps, later used to keep channel values
380
    final int[] tempPixels = new int[ srcWidth ];
381
    // create reusable row to minimize memory overhead
382
    final byte[] srcPixels = new byte[ srcWidth * nrChannels ];
383
    final boolean useChannel3 = nrChannels > 3;
384
385
    for( int k = start; k < srcHeight; k = k + delta ) {
386
      ImageUtils.getPixelsBGR( srcImg, k, srcWidth, srcPixels, tempPixels );
387
388
      for( int i = dstWidth - 1; i >= 0; i-- ) {
389
        int sampleLocation = i * nrChannels;
390
        final int max = horizontalSubsamplingData.arrN[ i ];
391
392
        float sample0 = 0.0f;
393
        float sample1 = 0.0f;
394
        float sample2 = 0.0f;
395
        float sample3 = 0.0f;
396
        int index = i * horizontalSubsamplingData.numContributors;
397
        for( int j = max - 1; j >= 0; j-- ) {
398
          float arrWeight = horizontalSubsamplingData.arrWeight[ index ];
399
          int pixelIndex =
400
            horizontalSubsamplingData.arrPixel[ index ] * nrChannels;
401
402
          sample0 += (srcPixels[ pixelIndex ] & 0xff) * arrWeight;
403
          sample1 += (srcPixels[ pixelIndex + 1 ] & 0xff) * arrWeight;
404
          sample2 += (srcPixels[ pixelIndex + 2 ] & 0xff) * arrWeight;
405
          if( useChannel3 ) {
406
            sample3 += (srcPixels[ pixelIndex + 3 ] & 0xff) * arrWeight;
407
          }
408
          index++;
409
        }
410
411
        workPixels[ k ][ sampleLocation ] = toByte( sample0 );
412
        workPixels[ k ][ sampleLocation + 1 ] = toByte( sample1 );
413
        workPixels[ k ][ sampleLocation + 2 ] = toByte( sample2 );
414
        if( useChannel3 ) {
415
          workPixels[ k ][ sampleLocation + 3 ] = toByte( sample3 );
416
        }
417
      }
418
    }
419
  }
420
421
  /**
422
   * Apply filter to sample horizontally from Src to Work
423
   */
424
  private void horizontallyFromSrcToWorkGray(
425
    BufferedImage srcImg, byte[][] workPixels, int start, int delta ) {
426
    // Used if we work on int based bitmaps, later used to keep channel values
427
    final int[] tempPixels = new int[ srcWidth ];
428
    // create reusable row to minimize memory overhead
429
    final byte[] srcPixels = new byte[ srcWidth ];
430
431
    for( int k = start; k < srcHeight; k = k + delta ) {
432
      ImageUtils.getPixelsBGR( srcImg, k, srcWidth, srcPixels, tempPixels );
433
434
      for( int i = dstWidth - 1; i >= 0; i-- ) {
435
        final int max = horizontalSubsamplingData.arrN[ i ];
436
437
        float sample0 = 0.0f;
438
        int index = i * horizontalSubsamplingData.numContributors;
439
        for( int j = max - 1; j >= 0; j-- ) {
440
          float arrWeight = horizontalSubsamplingData.arrWeight[ index ];
441
          int pixelIndex = horizontalSubsamplingData.arrPixel[ index ];
442
443
          sample0 += (srcPixels[ pixelIndex ] & 0xff) * arrWeight;
444
          index++;
445
        }
446
447
        workPixels[ k ][ i ] = toByte( sample0 );
448
      }
449
    }
450
  }
451
452
  private static byte toByte( final float f ) {
453
    if( f < 0 ) {
454
      return 0;
455
    }
456
457
    return (byte) (f > MAX_CHANNEL_VALUE ? MAX_CHANNEL_VALUE : f + 0.5f);
458
  }
459
460
  protected int getResultBufferedImageType( BufferedImage srcImg ) {
461
    return nrChannels == 3
462
      ? TYPE_3BYTE_BGR
463
      : nrChannels == 4
464
      ? TYPE_4BYTE_ABGR
465
      : srcImg.getSampleModel().getDataType() == TYPE_USHORT
466
      ? TYPE_USHORT_GRAY
467
      : TYPE_BYTE_GRAY;
468
  }
469
}
1470
A src/main/java/com/keenwrite/processors/DefinitionProcessor.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors;
3
4
import java.util.Map;
5
6
import static com.keenwrite.processors.text.TextReplacementFactory.replace;
7
8
/**
9
 * Processes interpolated string definitions in the document and inserts
10
 * their values into the post-processed text. The default variable syntax is
11
 * {@code $variable$}.
12
 */
13
public class DefinitionProcessor extends ExecutorProcessor<String> {
14
15
  private final Map<String, String> mDefinitions;
16
17
  /**
18
   * Constructs a processor capable of interpolating string definitions.
19
   *
20
   * @param successor Subsequent link in the processing chain.
21
   * @param context   Contains resolved definitions map.
22
   */
23
  public DefinitionProcessor(
24
      final Processor<String> successor,
25
      final ProcessorContext context ) {
26
    super( successor );
27
    mDefinitions = context.getResolvedMap();
28
  }
29
30
  /**
31
   * Processes the given text document by replacing variables with their values.
32
   *
33
   * @param text The document text that includes variables that should be
34
   *             replaced with values when rendered as HTML.
35
   * @return The text with all variables replaced.
36
   */
37
  @Override
38
  public String apply( final String text ) {
39
    return replace( text, getDefinitions() );
40
  }
41
42
  /**
43
   * Returns the map to use for variable substitution.
44
   *
45
   * @return A map of variable names to values.
46
   */
47
  protected Map<String, String> getDefinitions() {
48
    return mDefinitions;
49
  }
50
}
151
A src/main/java/com/keenwrite/processors/ExecutorProcessor.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors;
3
4
import java.util.Optional;
5
import java.util.concurrent.atomic.AtomicReference;
6
7
/**
8
 * Responsible for transforming data through a variety of chained handlers.
9
 *
10
 * @param <T> The data type to process.
11
 */
12
public class ExecutorProcessor<T> implements Processor<T> {
13
14
  /**
15
   * The next link in the processing chain.
16
   */
17
  private final Processor<T> mNext;
18
19
  protected ExecutorProcessor() {
20
    this( null );
21
  }
22
23
  /**
24
   * Constructs a new processor having a given successor.
25
   *
26
   * @param successor The next processor in the chain.
27
   */
28
  public ExecutorProcessor( final Processor<T> successor ) {
29
    mNext = successor;
30
  }
31
32
  /**
33
   * Calls every link in the chain to process the given data.
34
   *
35
   * @param data The data to transform.
36
   * @return The data after processing by every link in the chain.
37
   */
38
  @Override
39
  public T apply( final T data ) {
40
    // Start processing using the first processor after the executor.
41
    Optional<Processor<T>> handler = next();
42
    final var result = new MutableReference( data );
43
44
    while( handler.isPresent() ) {
45
      handler = handler.flatMap( p -> {
46
        result.set( p.apply( result.get() ) );
47
        return p.next();
48
      } );
49
    }
50
51
    return result.get();
52
  }
53
54
  @Override
55
  public Optional<Processor<T>> next() {
56
    return Optional.ofNullable( mNext );
57
  }
58
59
  /**
60
   * A minor micro-optimization, since the processors cannot be run in parallel,
61
   * avoid using an {@link AtomicReference} during processor execution. This
62
   * is about twice as fast for the first four processor links in the chain.
63
   */
64
  private final class MutableReference {
65
    private T mObject;
66
67
    MutableReference( final T object ) {
68
      set( object );
69
    }
70
71
    void set( final T object ) {
72
      mObject = object;
73
    }
74
75
    T get() {
76
      return mObject;
77
    }
78
  }
79
}
180
A src/main/java/com/keenwrite/processors/HtmlPreviewProcessor.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors;
3
4
import com.keenwrite.preview.HtmlPreview;
15
6
/**
7
 * Responsible for notifying the {@link HtmlPreview} when the succession
8
 * chain has updated. This 
9
 * from the
10
 * before the
11
 * processor
A src/main/java/com/keenwrite/processors/IdentityProcessor.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors;
3
4
/**
5
 * Responsible for transforming a string into itself. This is used at the
6
 * end of a processing chain when no more processing is required.
7
 */
8
public final class IdentityProcessor extends ExecutorProcessor<String> {
9
  public static final IdentityProcessor IDENTITY = new IdentityProcessor();
10
11
  /**
12
   * Constructs a new instance having no successor (the default successor is
13
   * {@code null}).
14
   */
15
  private IdentityProcessor() {
16
  }
17
18
  /**
19
   * Returns the given string without modification.
20
   *
21
   * @param s The string to return.
22
   * @return The value of s.
23
   */
24
  @Override
25
  public String apply( final String s ) {
26
    return s;
27
  }
28
}
129
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;
17
A src/main/java/com/keenwrite/processors/PreformattedProcessor.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors;
13
4
/**
5
 * This is the default processor used when an unknown file name extension is
6
 * encountered. It processes the text by enclosing it in an HTfinal
A src/main/java/com/keenwrite/processors/Processor.java
1
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved.
A src/main/java/com/keenwrite/processors/ProcessorContext.java
1
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved.areioconstantsconstants
A src/main/java/com/keenwrite/processors/ProcessorFactory.java
1
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved.ferences.Workspace
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;
13
4
import com.keenwrite.preferences.Key;
5
import com.keenwrite.preferences.Workspace;
6
import com.keenwrite.ui.heuristics.WordCounter;
7
import javafx
A src/main/java/com/keenwrite/processors/XmlProcessor.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwriteConfigurationom.IgnorableSpaceStrippingRulecom.keenwrite.events.StatusEvent.clue;
3
import static.newInstance;final class XmlProcessor extends ExecutorProcessor<String>
4
XMLInputFactory mXmlInputFactory = newInstance();
5
  private final Configuration mConfiguration = new Configuration();
6
  privatemTransformerFactory =
7
   mConfiguration); mTfinal Path mPsuccontext   Contains
8
    final Processor<String> successor,
9
    final ProcessorContext context ) {
10
    super( successor );
11
    mPath = context.getDocumentPathmTransformerF    final var options = mConfiguration.getParseOptions();
12
    options.setSpaceStrippingRule( IgnorableSpaceStrippingRule.getInstance()applyclue( ex );try(
13
      final vafinal va    final var  final var  // TODO: Use FileWatchService// mSnitchTransformer that transforms XML documents using saidInstantiate transformer failed.
14
   */mTmTmTfinal varvar xmlDirectory = m     varvafinal var reader = createXmlEventReader( sr );
15
      varvar count = 0varvar pi = (varmlmXmlInputFactorymTclueclueforclue( ex );
16
  }
17
}
118
A src/main/java/com/keenwrite/processors/markdown/BaseMarkdownProcessor.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors.markdown;
13
4
import com.keenwrite.processors.ExecutorProcessor;
5
import com.keenwrite.processors.Processor;
6
import com.keenwrite.processors.Processo
7
    if( {
8
      }
A src/main/java/com/keenwrite/processors/markdown/MarkdownProcessor.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors.markdown;
13
4
import com.keenwrite.io.MediaType;
5
import com.keenwrite.processors.DefinitionProcessor;
6
import com.keenwrite.processors.Processor;
7
imp
A src/main/java/com/keenwrite/processors/markdown/extensions/CaretExtension.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved..extensions;
2
3
import com.keenwrite.Caret;
4
import com.keenwrite.constants.Constants;
5
import com.keenwrite.processors.ProcessorCoext.tables.TableBlockconstants.extensions.EmptyNode.EMPTY_NODEBuilderextends HtmlRendererAdapter {
6
7
  private final CaretProcessomCaret = context.getCaret(Processoontext ) mCaret;
8
    private boolean mAdded final Caret// Optimization: if a caret is inserted, don't try to find another.
9
      if( mAdded ) {
10
        return;
11
      }
12
13
      // If a table block has been earmarked with an empty node, it means
14
      // another extension has generated code from an external source. The
15
      // Markdown processor won't be able to determine the caret position
16
      // with any semblance of accuracy, so skip the element. This usually
17
      // happens with tables, but in theory any Markdown generated from an
18
      // external source (e.g., an R script) could produce text that has no
19
      // caret position that can be calculated.
20
      var table = curr;
21
22
      if( !(curr instanceof TableBlock) ) {
23
        table = curr.getAncestorOfType( TableBlock.class );
24
      }
25
26
      // The table was generated outside the document
27
      if( table != null && table.getLastChild() == EMPTY_NODE ) {
28
        return;
29
      }
30
31
      final var outside = mCaret.isAfterText() ? 1 : 0; + outside        // This line empowerthe
32
        // We're done until the user moves the caret (micro-optimization)
33
        mAdded = true;
34
      }
35
    }
36
  }
37
}
138
A src/main/java/com/keenwrite/processors/markdown/extensions/DocumentOutlineExtension.java
1
package com.keenwrite.processors.markdown.extensions;
2
3
import com.keenwrite.processors.Processor;
4
import com.vladsch.flexmark.ast.Heading;
5
import com.vladsch.flexmark.parser.Parser.Builder;
6
import com.vladsch.flexmark.parser.Parser.ParserExtension;
7
import com.vladsch.flexmark.parser.block.NodePostProcessor;
8
import com.vladsch.flexmark.parser.block.NodePostProcessorFactory;
9
import com.vladsch.flexmark.util.ast.Document;
10
import com.vladsch.flexmark.util.ast.Node;
11
import com.vladsch.flexmark.util.ast.NodeTracker;
12
import com.vladsch.flexmark.util.data.MutableDataHolder;
13
import org.jetbrains.annotations.NotNull;
14
15
import java.util.regex.Pattern;
16
17
import static com.keenwrite.events.ParseHeadingEvent.fireNewHeadingEvent;
18
import static com.keenwrite.events.ParseHeadingEvent.fireNewOutlineEvent;
19
20
public final class DocumentOutlineExtension implements ParserExtension {
21
  private static final Pattern sRegex = Pattern.compile( "^(#+)" );
22
23
  private final Processor<String> mProcessor;
24
25
  private DocumentOutlineExtension( final Processor<String> processor ) {
26
    mProcessor = processor;
27
  }
28
29
  @Override
30
  public void parserOptions( final MutableDataHolder options ) {}
31
32
  @Override
33
  public void extend( final Builder builder ) {
34
    builder.postProcessorFactory( new Factory() );
35
  }
36
37
  public static DocumentOutlineExtension create(
38
    final Processor<String> processor ) {
39
    return new DocumentOutlineExtension( processor );
40
  }
41
42
  private class HeadingNodePostProcessor extends NodePostProcessor {
43
    @Override
44
    public void process(
45
      @NotNull final NodeTracker state, @NotNull final Node node ) {
46
      final var heading = mProcessor.apply( node.getChars().toString() );
47
      final var matcher = sRegex.matcher( heading );
48
49
      if( matcher.find() ) {
50
        final var level = matcher.group().length();
51
        final var text = heading.substring( level );
52
        final var offset = node.getStartOffset();
53
        fireNewHeadingEvent( level, text, offset );
54
      }
55
    }
56
  }
57
58
  public class Factory extends NodePostProcessorFactory {
59
    public Factory() {
60
      super( false );
61
      addNodes( Heading.class );
62
    }
63
64
    @NotNull
65
    @Override
66
    public NodePostProcessor apply( @NotNull final Document document ) {
67
      fireNewOutlineEvent();
68
      return new HeadingNodePostProcessor();
69
    }
70
  }
71
}
172
A src/main/java/com/keenwrite/processors/markdown/extensions/EmptyNode.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors.markdown.extensions;
13
4
import com.vladsch.flexmark.util.ast.Node;
5
import com.vladsch.flexmark.util.sequence.BasedSequence;
6
import org.jetbrains.
A src/main/java/com/keenwrite/processors/markdown/extensions/HtmlRendererAdapter.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors.markdown.extensions;
3
4
import com.vladsch.flexmark.util.data.MutableDataHolder;
5
import org.jetbrains.annotations.NotNull;
16
7
import static co
A src/main/java/com/keenwrite/processors/markdown/extensions/ImageLinkExtension.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors.markdown.extensions;
13
4
import com.keenwrite.ExportFormat;
5
import com.keenwrite.preferences.Workspace;
6
import com.keenwrite.processorsProcessorCont
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
 closClos@Overridehtml.closeTag( HTML_DIV );
6
  }
7
}
18
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.preferences.WorkspaceDefinitioProcessorContextmarkdown.preferences.WorkspaceKeys.KEY_IMAGES_SERVER  private final ProcessorContext mContext;
15
6
  publ, final ProcessorContext contextassert context  mContext = context, final ProcessorContext context, context/**
7
   * Responsible for generating images from a fenced block that contains a
8
   * diagram reference.
9
   */
10
  private class CugetSourceUrl( type, encodedgetSourceUrl( final String type, final String encoded ) {
11
      return
12
        format(getDiagramServerName(), type, encoded );Workspace getWorkspace() {
13
      return mContext.getWorkspace();getDiagramServerName() {
14
      return getWorkspace().toString( KEY_IMAGES_SERVER
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;
13
4
import com.keenwrite.processors.markdown.extensions.HtmlRendererAdapter;
5
import com.vladsch.flexmark.html.HtmlRender" +
6
      "
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;
16
7
import java.util.Arradiv element.
8
 */
9
void export
A src/main/java/com/keenwrite/processors/markdown/extensions/r/RExtension.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors.markdown.extensions.r;
13
4
import com.keenwrite.processors.Processor;
5
import com.keenwrite.processors.ProcessorContext;
6
import com.keenwrite.processr.InlineRProcessor;
7
import com.keenwrite.processr.RProcessor;
8
import com.keenwrite.sigils.RSigilOperast.Textutil.data.Mutablemarkdown.extensions.EmptyNode.EMPTY_NODE;ParserExtensionSigilOperExtension implements  INLINE_FACTORY = InlineParser::new;
9
  private final RProcessor mProcessExtension(
10
    final RProcessor processor,Processor = processProcessor processor,Extension( processNLINE_FACTORYparserOptions( final MutableDataHolder options ) {InlineRProcessInlineRProcess options,
11
          );
12
      mProcessor.init(SigilOperfinal&& mProcessor.isReady()code.startsWith( RSigilOperator.PREFIX            final var rText = mProcessnew Text( rText  elsenode.getFir  // Mark the node as being generated code, such as text returned
13
                // from an R function.
14
                node.appendChild( EMPTY_NODE );
15
  
A src/main/java/com/keenwrite/processors/markdown/extensions/r/ROutputProcessor.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors.markdown.extensions.r;
3
4
import com.keenwrite.processors.ExecutorProcessor;
5
import com.keenwrite.processors.r.InlineRProcessor;
6
import com.keenwrite.processors.markdown.MarkdownProcessor;
7
import com.keenwrite.processors.markdown.extensions.tex.TeXExtension;
8
import com.vladsch.flexmark.ast.Paragraph;
9
import com.vladsch.flexmark.ast.Text;
10
import com.vladsch.flexmark.html.HtmlRenderer;
11
import com.vladsch.flexmark.parser.Parser;
12
import com.vladsch.flexmark.util.ast.IParse;
13
import com.vladsch.flexmark.util.ast.IRender;
14
15
/**
16
 * Responsible for parsing the output from an R eval statement. This class
17
 * is used to avoid an circular dependency whereby the {@link InlineRProcessor}
18
 * must treat the output from an R function call as Markdown, which would
19
 * otherwise require a {@link MarkdownProcessor} instance; however, the
20
 * {@link MarkdownProcessor} class gives precedence to its extensions, which
21
 * means the {@link TeXExtension} will be executed <em>before</em> the
22
 * {@link InlineRProcessor}, thereby being exposed to backticks in a TeX
23
 * macro---a syntax error. To break the cycle, the {@link InlineRProcessor}
24
 * uses this class instead of {@link MarkdownProcessor}.
25
 */
26
public class ROutputProcessor extends ExecutorProcessor<String> {
27
  private final IParse mParser = Parser.builder().build();
28
  private final IRender mRenderer = HtmlRenderer.builder().build();
29
30
  @Override
31
  public String apply( final String markdown ) {
32
    var node = mParser.parse( markdown ).getFirstChild();
33
34
    if( node == null ) {
35
      node = new Text();
36
    }
37
    else if( node.isOrDescendantOfType( Paragraph.class ) ) {
38
      node = new Text( node.getChars() );
39
    }
40
41
    // Trimming prevents displaced commas and unwanted newlines.
42
    return mRenderer.render( node ).trim();
43
  }
44
}
145
A src/main/java/com/keenwrite/processors/markdown/extensions/tex/TeXExtension.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors.markdown.extensions.tex;
3
4
import com.keenwrite.ExportFormat;
5
import com.keenwrite.processors.Processor;
6
import com.keenwrite.processors.ProcessorContext;
7
import com.keenwrite.processors.markdown.extensions.HtmlRendererAdapter;
8
import com.keenwrite.processors.markdown.extensions.tex.TexNodeRenderer.Factory;
9
import com.vladsch.flexmark.html.HtmlRenderer;
10
import com.vladsch.flexmark.parser.Parser;
11
import com.vladsch.flexmark.util.data.MutableDataHolder;
12
import org.jetbrains.annotations.NotNull;
13
14
import static com.vladsch.flexmark.parser.Parser.ParserExtension;
15
16
/**
17
 * Responsible for wrapping delimited TeX code in Markdown into an XML element
18
 * that the HTML renderer can handle. For example, {@code $E=mc^2$} becomes
19
 * {@code <tex>E=mc^2</tex>} when passed to HTML renderer. The HTML renderer
20
 * is responsible for converting the TeX code for display. This avoids inserting
21
 * SVG code into the Markdown document, which the parser would then have to
22
 * iterate---a <em>very</em> wasteful operation that impacts front-end
23
 * performance.
24
 */
25
public class TeXExtension extends HtmlRendererAdapter
26
  implements ParserExtension {
27
28
  /**
29
   * Responsible for pre-parsing the input.
30
   */
31
  private final Processor<String> mProcessor;
32
33
  /**
34
   * Controls how the node renderer produces TeX code within HTML output.
35
   */
36
  private final ExportFormat mExportFormat;
37
38
  private TeXExtension(
39
    final Processor<String> processor, final ProcessorContext context  ) {
40
    mProcessor = processor;
41
    mExportFormat = context.getExportFormat();
42
  }
43
44
  /**
45
   * Creates an extension capable of handling delimited TeX code in Markdown.
46
   *
47
   * @return The new {@link TeXExtension}, never {@code null}.
48
   */
49
  public static TeXExtension create(
50
    final Processor<String> processor, final ProcessorContext context  ) {
51
    return new TeXExtension( processor, context );
52
  }
53
54
  /**
55
   * Adds the TeX extension for HTML document export types.
56
   *
57
   * @param builder      The document builder.
58
   * @param rendererType Indicates the document type to be built.
59
   */
60
  @Override
61
  public void extend( @NotNull final HtmlRenderer.Builder builder,
62
                      @NotNull final String rendererType ) {
63
    if( "HTML".equalsIgnoreCase( rendererType ) ) {
64
      builder.nodeRendererFactory( new Factory( mExportFormat, mProcessor ) );
65
    }
66
  }
67
68
  @Override
69
  public void extend( final Parser.Builder builder ) {
70
    builder.customDelimiterProcessor( new TeXInlineDelimiterProcessor() );
71
  }
72
73
  @Override
74
  public void parserOptions( final MutableDataHolder options ) {
75
  }
76
}
177
A src/main/java/com/keenwrite/processors/markdown/extensions/tex/TeXInlineDelimiterProcessor.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors.markdown.extensions.tex;
3
4
import com.vladsch.flexmark.parser.InlineParser;
5
import com.vladsch.flexmark.parser.core.delimiter.Delimiter;
6
import com.vladsch.flexmark.parser.delimiter.DelimiterProcessor;
7
import com.vladsch.flexmark.parser.delimiter.DelimiterRun;
8
import com.vladsch.flexmark.util.ast.Node;
9
10
public class TeXInlineDelimiterProcessor implements DelimiterProcessor {
11
12
  @Override
13
  public void process( final Delimiter opener,
14
                       final Delimiter closer,
15
                       final int delimitersUsed ) {
16
    final var node = new TexNode( opener, closer );
17
    opener.moveNodesBetweenDelimitersTo( node, closer );
18
  }
19
20
  @Override
21
  public char getOpeningCharacter() {
22
    return '$';
23
  }
24
25
  @Override
26
  public char getClosingCharacter() {
27
    return '$';
28
  }
29
30
  @Override
31
  public int getMinLength() {
32
    return 1;
33
  }
34
35
  /**
36
   * Allow for $ or $$.
37
   *
38
   * @param opener One or more opening delimiter characters.
39
   * @param closer One or more closing delimiter characters.
40
   * @return The number of delimiters to use to determine whether a valid
41
   * opening delimiter expression is found.
42
   */
43
  @Override
44
  public int getDelimiterUse(
45
    final DelimiterRun opener, final DelimiterRun closer ) {
46
    return 1;
47
  }
48
49
  @Override
50
  public boolean canBeOpener( final String before,
51
                              final String after,
52
                              final boolean leftFlanking,
53
                              final boolean rightFlanking,
54
                              final boolean beforeIsPunctuation,
55
                              final boolean afterIsPunctuation,
56
                              final boolean beforeIsWhitespace,
57
                              final boolean afterIsWhiteSpace ) {
58
    return leftFlanking;
59
  }
60
61
  @Override
62
  public boolean canBeCloser( final String before,
63
                              final String after,
64
                              final boolean leftFlanking,
65
                              final boolean rightFlanking,
66
                              final boolean beforeIsPunctuation,
67
                              final boolean afterIsPunctuation,
68
                              final boolean beforeIsWhitespace,
69
                              final boolean afterIsWhiteSpace ) {
70
    return rightFlanking;
71
  }
72
73
  @Override
74
  public Node unmatchedDelimiterNode(
75
    final InlineParser inlineParser, final DelimiterRun delimiter ) {
76
    return null;
77
  }
78
79
  @Override
80
  public boolean skipNonOpenerCloser() {
81
    return false;
82
  }
83
}
184
A src/main/java/com/keenwrite/processors/markdown/extensions/tex/TexNode.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors.markdown.extensions.tex;
3
4
import com.vladsch.flexmark.ast.DelimitedNodeImpl;
5
import com.vladsch.flexmark.parser.core.delimiter.Delimiter;
16
7
public return mOpener; return mCloser;
A src/main/java/com/keenwrite/processors/markdown/extensions/tex/TexNodeRenderer.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved.extensionsProcessor
2
    false  true  true private final boolean mIncludeDelimiter;
13
4
    private final boolean includeDelimiter ) {
5
      mIncludeDelimiter = includeDelimiter;
6
    }
7
t =content =
8
        mIncludeDelimiter
9
          ? node.getOpeningDelimiter() + text + node.getClosingDelimiter()
10
          : text;content
A src/main/java/com/keenwrite/processors/r/InlineRProcessor.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors.r;
3
4
import com.keenwrite.preferences.Workspace;
5
import com.keenwrite.processors.DefinitionProcessor;
6
import com.keenwrite.processors.Processor;
7
import com.keenwrite.processors.ProcessorContext;
8
import com.keenwrite.processors.markdown.extensions.r.ROutputProcessor;
9
import com.keenwrite.util.BoundedCachekeenwrite.constantskeenwritekeenwrite.events.StatusEvent.cluekeenwrite.preferences.WorkspaceKeys.*keenwritekeenwritekeenwritejava.lang.Math.max  private final Processor<String> mPostProcessor = new ROutputProcessor(), constrained to
10
   * avoid running out of memoryString> mEvalCache =
11
    new BoundedCache<>( 512private final Workspace mWorkspacesuccontext   Contains rfinal Processor<String> successor,
12
    final ProcessorContext context ) {
13
    super( successor, context );
14
15
    mWorkspace = context.getWorkspace(( __( __// TODO: Watch the "R" property keys in the workspace, directly.
16
17
    // If the user saves the preferences, make sure that any R-related settings
18
    // changes are applied.
19
//    getWorkspace////        init();
20
//        setDirty( false );
21
//      }
22
//if initialization completed and all variables were
23
   * replaced; {@code false} if any variables remain.
24
   */
25
  public boolean init() {
26
final var defBegan = mWorkspace.toString( KEY_DEF_DELIM_BEGAN );
27
      final var defEnded = mWorkspace.toString( KEY_DEF_DELIM_ENDED );
28
29
      map.put( defBegan + "application.r.working.directory" + defEnded, dir );
30
31
      final var replaced = replace( b;
32
      final var bIndex = replaced.indexOf( defBegan );
33
34
      // If there's a delimiter in the replaced text it means not all variables
35
      // are bound, which is an error.
36
      if( bIndex >= 0 ) {
37
        var eIndex = replaced.indexOf( defEnded );
38
        eIndex = (eIndex == -1) ? replaced.length() - 1 : max( bIndex, eIndex );
39
40
        final var def = replaced.substring(
41
          bIndex + defBegan.length(), eIndex );
42
        clue( "Main.status.error.bootstrap.eval",
43
              format( "%s%s%s", defBegan, def, defEnded ) );
44
45
        return false;
46
      }
47
      else {
48
        eval( replaced );
49
      }
50
    }
51
52
    return true;
53
  }
54
55
  /**
56
   * Empties the cache.
57
   */
58
  public void clear() {
59
    mEvalCache.clear();the opening tokenclosing tokenvarevalCached( r )    // Informclue( STATUS_PARSE_ERROR, ex.getMessage(), currIndex );
60
String evalCached__ -> evalHtml( r ) );
61
  }
62
63
  /**
64
   * Converts the given string to HTML, trimming new lines, and inlining
65
   * the text if it is a paragraph. Otherwise, the resulting HTML is most likely
66
   * complex (e.g., a Markdown table) and should be rendered as its HTML
67
   * equivalr The R expression to evaluate then convert to HTML.
68
   * @return The result from the R expression as an HTML element.
69
   */
70
  evalHtmlPostProcessor.apply(String evalENGINE.eval( r ).toString();var50 ) );
71
      clue( get( "Main.status.error.r, ex );
72
      return "";
73
    }getValue().toPath();
74
  }
75
76
  private Workspace().fileProperty( KEY_R_DIR .getValue();
77
  }
78
79
  private Property<String>Workspace().valuesProperty( KEY_R_SCRIPT );
80
  }
81
82
  private Workspace getWorkspace() {
83
    return mWorkspace;
84
  }
85
}
186
A src/main/java/com/keenwrite/processors/r/RProcessor.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors.r;
3
4
import com.keenwrite.processors.ExecutorProcessor;
5
import com.keenwrite.processors.Processor;
6
import com.keenwrite.processors.ProcessorContex
7
  privat}
18
A src/main/java/com/keenwrite/processors/r/RVariableProcessor.java
1
/* Copyright 2020-2021 -- All rights reserved. */
2
package com.keenwrite.processors.r;
3
4
import com.keenwrite.preferences.Workspace;
5
import com.keenwrite.processors.DefinitionProcessor;
6
import com.keenwrite.processors.ProcessorContext;
7
import com.keenwrite.sigils.RSigilOperator;
8
import com.keenwrite.sigils.SigilOperator;
9
import com.keenwrite.sigils.YamlSigilOperatorimport static com.keenwrite.preferences.WorkspaceKeys.*/
10
public finalrivate final SigilOperator mSigilOperator;final InlineRProcessor irp, final ProcessorContext context ) {
11
    super( irp, context );
12
    mSigilOperator = createSigilOperator( context.getWorkspace()entokenentoken(var rMap = new HashvarmSigilOperator.entoken( key ), escap "SameParameterValue" vaigilOperator createSigilOperator( final Workspace workspace ) {
13
    final var tokens = workspace.toTokens(
14
      KEY_R_DELIM_BEGAN, KEY_R_DELIM_ENDED );
15
    final var antecedent = createDefinitionOperator( workspace );
16
    return new RSigilOperator( tokens, antecedent igilOperator createDefinitionOperator( final Workspace workspace ) {
17
    final var tokens = workspace.toTokens(
18
      KEY_DEF_DELIM_BEGAN, KEY_DEF_DELIM_ENDED );
19
    return new YamlSigilOperator( tokens );
20
  }
21
}
122
A src/main/java/com/keenwrite/processors/text/AbstractTextReplacer.java
1
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved.
A src/main/java/com/keenwrite/processors/text/AhoCorasickReplacer.java
1
1
/* Copyright 2020-2021
2
 * All rights reserved.
3
 * -- All rights reserved.
A src/main/java/com/keenwrite/processors/text/StringUtilsReplacer.java
1
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved.
A src/main/java/com/keenwrite/processors/text/TextReplacementFactory.java
1
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwritestatic finalstatic finalslower
3
    //algorithm implementation.
A src/main/java/com/keenwrite/processors/text/TextReplacer.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors.text;
3
4
import java.util.Map;
5
6
/**
7
 * Defines the ability to replace text given a set of keys and values.
8
 */
9
public interface TextReplacer {
10
11
  /**
12
   * Searches through the given text for any of the keys given in the map and
13
   * replaces the keys that appear in the text with the key's corresponding
14
   * value.
15
   *
16
   * @param text The text that contains zero or more keys.
17
   * @param map  The set of keys mapped to replacement values.
18
   * @return The given text with all keys replaced with corresponding values.
19
   */
20
  String replace( String text, Map<String, String> map );
21
}
122
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
A src/main/java/com/keenwrite/search/SearchModel.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.search;
13
4
import com.keenwrite.util.CyclicIterator;
5
import javafx.beans.property.ObjectProperty;
6
import javafx.beans.property.SimpleObjectProperty;
7
import jafinal
A src/main/java/com/keenwrite/service/Service.java
1
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved.
A src/main/java/com/keenwrite/service/Settings.java
1
1
/* Copyright 2020-2021
2
 * All rights reserved.
3
 * -- All rights reserved.
A src/main/java/com/keenwrite/service/events/Notification.java
1
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved.
A src/main/java/com/keenwrite/service/events/Notifier.java
1
/* Copyright 2020-2021 -- All rights reserved. */
2
package com.keenwritenio.file.PathPath path,
3
    String titleKey,
4
Path path,
5
String title,
16
A src/main/java/com/keenwrite/service/events/impl/ButtonOrderPane.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.service.events.impl;
3
4
import javafx.scene.Node;
5
import javafx.scene.control.ButtonBar;
6
import javafx.scene.control.DialogPane;
7
8
import static com.keenwrite.constants.Constants.sSettings;
9
import static javafx.scene.control.ButtonBar.BUTTON_ORDER_WINDOWS;
10
11
/**
12
 * Ensures a consistent button order for alert dialogs across platforms (because
13
 * the default button order on Linux defies all logic).
14
 */
15
public class ButtonOrderPane extends DialogPane {
16
  public ButtonOrderPane() {
17
  }
18
19
  @Override
20
  protected Node createButtonBar() {
21
    final var node = (ButtonBar) super.createButtonBar();
22
    node.setButtonOrder( getButtonOrder() );
23
    return node;
24
  }
25
26
  private String getButtonOrder() {
27
    return sSettings.getSetting(
28
      "dialog.alert.button.order.windows", BUTTON_ORDER_WINDOWS );
29
  }
30
}
131
A src/main/java/com/keenwrite/service/events/impl/DefaultNotification.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.service.events.impl;
3
4
import com.keenwrite.service.events.Notification;
5
6
import java.text.MessageFormat;
7
8
/**
9
 * Responsible for alerting the user to prominent information.
10
 */
11
public class DefaultNotification implements Notification {
12
13
  private final String title;
14
  private final String content;
15
16
  /**
17
   * Constructs default message text for a notification.
18
   *
19
   * @param title   The message title.
20
   * @param message The message content (needs formatting).
21
   * @param args    The arguments to the message content that must be formatted.
22
   */
23
  public DefaultNotification(
24
      final String title,
25
      final String message,
26
      final Object... args ) {
27
    this.title = title;
28
    this.content = MessageFormat.format( message, args );
29
  }
30
31
  @Override
32
  public String getTitle() {
33
    return this.title;
34
  }
35
36
  @Override
37
  public String getContent() {
38
    return this.content;
39
  }
40
41
}
142
A src/main/java/com/keenwrite/service/events/impl/DefaultNotifier.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.service.events.impl;
13
4
import com.keenwrite.service.events.Notification;
5
import com.keenwrite.service.events.Notifier;
6
import javafx.scene.control.Alert;
7
impconstants
A src/main/java/com/keenwrite/service/impl/DefaultSettings.java
1
/* Copyright 2020-2021 -- All rights reserved. */
2
package com.keenwritecom.keenwrite.service.Settings
3
import static com.keenwrite.constants.Constants.PATH_PROPERTIES_SETTINGS/
4
public finalmProperties = createProperties() {      
5
   {
6
    final varvarvar reade
7
         eader );
8
      } catch( final exPATH_PROPERTIES_SETTINGSmProperties;
9
  }
10
}
111
A src/main/java/com/keenwrite/sigils/RSigilOperator.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.sigils;
3
4
import static com.keenwrite.sigils.YamlSigilOperator.KEY_SEPARATOR_DEF;
5
6
/**
7
 * Brackets variable names between {@link #PREFIX} and {@link #SUFFIX} sigils.
8
 */
9
public final class RSigilOperator extends SigilOperator {
10
  private static final char KEY_SEPARATOR_R = '$';
11
12
  public static final String PREFIX = "`r#";
13
  public static final char SUFFIX = '`';
14
15
  /**
16
   * Definition variables are inserted into the document before R variables,
17
   * so this is required to reformat the definition variable suitable for R.
18
   */
19
  private final SigilOperator mAntecedent;
20
21
  /**
22
   * Constructs a new {@link RSigilOperator} capable of wrapping tokens around
23
   * variable names (keys).
24
   *
25
   * @param tokens     The starting and ending tokens.
26
   * @param antecedent The operator to use to undo any previous entokenizing.
27
   */
28
  public RSigilOperator( final Tokens tokens, final SigilOperator antecedent ) {
29
    super( tokens );
30
31
    mAntecedent = antecedent;
32
  }
33
34
  /**
35
   * Returns the given string with backticks prepended and appended. The
36
   *
37
   * @param key The string to adorn with R token delimiters.
38
   * @return PREFIX + delimiterBegan + variableName + delimiterEnded + SUFFIX.
39
   */
40
  @Override
41
  public String apply( final String key ) {
42
    assert key != null;
43
    return PREFIX + getBegan() + key + getEnded() + SUFFIX;
44
  }
45
46
  /**
47
   * Transforms a definition key (bracketed by token delimiters) into the
48
   * expected format for an R variable key name.
49
   * <p>
50
   * The algorithm to entoken a definition name is faster than
51
   * {@link String#replace(char, char)}. Faster still would be to cache the
52
   * values, but that would mean managing the cache when the user changes
53
   * the beginning and ending of the R delimiters. This code gives about a
54
   * 2% performance boost when scrolling using cursor keys. After the JIT
55
   * warms up, this super-minor bottleneck vanishes.
56
   * </p>
57
   *
58
   * @param key The variable name to transform, can be empty but not null.
59
   * @return The transformed variable name.
60
   */
61
  public String entoken( final String key ) {
62
    final var detokened = new StringBuilder( key.length() );
63
    detokened.append( "v$" );
64
    detokened.append( mAntecedent.detoken( key ) );
65
66
    // The 3 is for "v$X" where X cannot be a period.
67
    for( int i = detokened.length() - 1; i >= 3; i-- ) {
68
      if( detokened.charAt( i ) == KEY_SEPARATOR_DEF ) {
69
        detokened.setCharAt( i, KEY_SEPARATOR_R );
70
      }
71
    }
72
73
    return detokened.toString();
74
  }
75
}
176
A src/main/java/com/keenwrite/sigils/SigilOperator.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.sigils;
3
4
import java.util.function.UnaryOperator;
5
6
/**
7
 * Responsible for updating definition keys to use a machine-readable format
8
 * corresponding to the type of file being edited. This changes a definition
9
 * key name based on some criteria determined by the factory that creates
10
 * implementations of this interface.
11
 */
12
public abstract class SigilOperator implements UnaryOperator<String> {
13
  private final Tokens mTokens;
14
15
  SigilOperator( final Tokens tokens ) {
16
    mTokens = tokens;
17
  }
18
19
  /**
20
   * Removes start and stop definition key delimiters from the given key. This
21
   * method does not check for delimiters, only that there are sufficient
22
   * characters to remove from either end of the given key.
23
   *
24
   * @param key The key adorned with start and stop tokens.
25
   * @return The given key with the delimiters removed.
26
   */
27
  String detoken( final String key ) {
28
    return key;
29
  }
30
31
  String getBegan() {
32
    return mTokens.getBegan();
33
  }
34
35
  String getEnded() {
36
    return mTokens.getEnded();
37
  }
38
39
  /**
40
   * Wraps the given key in the began and ended tokens. This may perform any
41
   * preprocessing necessary to ensure the transformation happens.
42
   *
43
   * @param key The variable name to transform.
44
   * @return The given key with tokens to delimit it (from the edited text).
45
   */
46
  public abstract String entoken( final String key );
47
}
148
A src/main/java/com/keenwrite/sigils/Tokens.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.sigils;
3
4
import javafx.beans.property.StringProperty;
5
6
import java.util.AbstractMap.SimpleImmutableEntry;
17
8
/**
9
 * Convenience class for pairing a start and an 
A src/main/java/com/keenwrite/sigils/YamlSigilOperator.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.sigilsfinalthat may have start and stopvar began = getBegan();
3
    final var ended = getEnded();
4
    final int bLength = began.length();
5
    final int eLength = ended.length();
6
    final var bIndex = key.indexOf( began );
7
    final var eIndex = key.indexOf( ended, bIndex );
8
    final var kLength = key.length();
9
10
    return key.substring(
11
      bIndex == -1 ? 0 : bLength, eIndex == -1 ? kLength : kLength - eLength );
12
  }
13
}
114
A src/main/java/com/keenwrite/spelling/api/SpellCheckListener.java
1
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved.
A src/main/java/com/keenwrite/spelling/api/SpellChecker.java
1
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved.
A src/main/java/com/keenwrite/spelling/api/package-info.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
3
/**
4
 * This package contains interfaces for spell checking implementations.
5
 */
6
package com.keenwrite.spelling.api;
17
A src/main/java/com/keenwrite/spelling/impl/PermissiveSpeller.java
1
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved.final
A src/main/java/com/keenwrite/spelling/impl/SymSpellSpeller.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwritekeenwrite.exceptions.MissingFileException;
3
import com.keenwrite.spelling.api.SpellCheckListener;
4
import com.keenwrite.spelling.io.BufferedReader;
5
import java.io.InputStreamReader;stream.Collectors;
6
7
import static com.keenwrite.constants.Constants.LEXICONS_DIRECTORY;
8
import static com.keenwrite.events.StatusEvent.clueimport static java.nio.charset.StandardCharsets.UTF_8BreakIterator mBreakIteratorspellchecker for a lexicon of words found in the specified
9
   * file.
10
   *
11
   * @param filename Lexicon language file (e.g., "en.txt"), or {@link PermissiveSpeller} if the
12
   * lexicon cannot be loaded final String filename ) {
13
    try {
14
      final var lexicon = readLexicon( filename );
15
      return SymSpellSpeller.forLexicon( lexicon );
16
    } catch( final Exception ex ) {
17
      clue( ex );
18
      return new PermissiveSpeller();
19
    }
20
  }
21
22
  private svafinal String text, final SpellCheckListenermBreakIteratormBreakIteratorvar lex =
23
// Get the lexeme for the possessive.
24
      final var pos = lex.endsWith( "'s" ) || lex.endsWith( "’s" );
25
      final var lexeme = pos ? lex.substring( 0, lex.length() - 2 ) : lexlexeme ) && !inLexicon( lexemelex,mBreakIterator@SuppressWarnings( "SameParameterValue" )
26
  private static Collection<String> readLexicon( final String filename )
27
    throws Exception {
28
    final var path = '/' + LEXICONS_DIRECTORY + '/' + filename;
29
30
    try( final var resource =
31
           SymSpellSpeller.class.getResourceAsStream( path ) ) {
32
      if( resource == null ) {
33
        throw new MissingFileException( path );
34
      }
35
36
      try( final var isr = new InputStreamReader( resource, UTF_8 );
37
           final var reader = new BufferedReader( isr ) ) {
38
        return reader.lines().collect( Collectors.toList() );
39
      }mSymSpell}
140
A src/main/java/com/keenwrite/spelling/impl/TextEditorSpeller.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.spelling.impl;
3
4
import com.keenwrite.spelling.api.SpellCheckListener;
5
import com.keenwrite.spelling.api.SpellChecker;
6
import com.vladsch.flexmark.parser.Parser;
7
import com.vladsch.flexmark.util.ast.NodeVisitor;
8
import com.vladsch.flexmark.util.ast.VisitHandler;
9
import org.fxmisc.richtext.StyleClassedTextArea;
10
import org.fxmisc.richtext.model.StyleSpansBuilder;
11
12
import java.util.Collection;
13
import java.util.concurrent.atomic.AtomicInteger;
14
15
import static com.keenwrite.spelling.impl.SymSpellSpeller.forLexicon;
16
import static java.util.Collections.emptyList;
17
import static java.util.Collections.singleton;
18
import static org.fxmisc.richtext.model.TwoDimensional.Bias.Forward;
19
20
/**
21
 * Responsible for checking the spelling of a document being edited.
22
 */
23
public final class TextEditorSpeller {
24
  /**
25
   * Only load the dictionary into memory once, because it's huge.
26
   */
27
  private static final SpellChecker sSpellChecker = forLexicon( "en.txt" );
28
29
  public TextEditorSpeller() {
30
  }
31
32
  /**
33
   * Delegates to {@link #spellcheck(StyleClassedTextArea, String, int)}.
34
   * call to spell check the entire document.
35
   */
36
  public void checkDocument( final StyleClassedTextArea editor ) {
37
    spellcheck( editor, editor.getText(), -1 );
38
  }
39
40
  /**
41
   * Listen for changes to the any particular paragraph and perform a quick
42
   * spell check upon it. The style classes in the editor will be changed to
43
   * mark any spelling mistakes in the paragraph. The user may then interact
44
   * with any misspelled word (i.e., any piece of text that is marked) to
45
   * revise the spelling.
46
   *
47
   * @param editor The text area containing paragraphs to spellcheck.
48
   */
49
  public void checkParagraphs( final StyleClassedTextArea editor ) {
50
    // Use the plain text changes so that notifications of style changes
51
    // are suppressed. Checking against the identity ensures that only
52
    // new text additions or deletions trigger proofreading.
53
    editor.plainTextChanges()
54
          .filter( p -> !p.isIdentity() ).subscribe( change -> {
55
56
      // Check current paragraph; the whole document was checked upon opening.
57
      final var offset = change.getPosition();
58
      final var position = editor.offsetToPosition( offset, Forward );
59
      final var paraId = position.getMajor();
60
      final var paragraph = editor.getParagraph( paraId );
61
      final var text = paragraph.getText();
62
63
      // Prevent doubling-up styles.
64
      editor.clearStyle( paraId );
65
66
      spellcheck( editor, text, paraId );
67
    } );
68
  }
69
70
  /**
71
   * Spellchecks a subset of the entire document.
72
   *
73
   * @param text   Look up words for this text in the lexicon.
74
   * @param paraId Set to -1 to apply resulting style spans to the entire
75
   *               text.
76
   */
77
  private void spellcheck(
78
    final StyleClassedTextArea editor, final String text, final int paraId ) {
79
    final var builder = new StyleSpansBuilder<Collection<String>>();
80
    final var runningIndex = new AtomicInteger( 0 );
81
82
    // The text nodes must be relayed through a contextual "visitor" that
83
    // can return text in chunks with correlative offsets into the string.
84
    // This allows Markdown, R Markdown, XML, and R XML documents to return
85
    // sets of words to check.
86
87
    final var node = mParser.parse( text );
88
    final var visitor = new TextVisitor( ( visited, bIndex, eIndex ) -> {
89
      // Treat hyphenated compound words as individual words.
90
      final var check = visited.replace( '-', ' ' );
91
92
      sSpellChecker.proofread( check, ( misspelled, prevIndex, currIndex ) -> {
93
        prevIndex += bIndex;
94
        currIndex += bIndex;
95
96
        // Clear styling between lexiconically absent words.
97
        builder.add( emptyList(), prevIndex - runningIndex.get() );
98
        builder.add( singleton( "spelling" ), currIndex - prevIndex );
99
        runningIndex.set( currIndex );
100
      } );
101
    } );
102
103
    visitor.visit( node );
104
105
    // If the running index was set, at least one word triggered the listener.
106
    if( runningIndex.get() > 0 ) {
107
      // Clear styling after the last lexiconically absent word.
108
      builder.add( emptyList(), text.length() - runningIndex.get() );
109
110
      final var spans = builder.create();
111
112
      if( paraId >= 0 ) {
113
        editor.setStyleSpans( paraId, 0, spans );
114
      }
115
      else {
116
        editor.setStyleSpans( 0, spans );
117
      }
118
    }
119
  }
120
121
  /**
122
   * TODO: #59 -- Replace using Markdown processor instantiated for Markdown
123
   * files.
124
   */
125
  private final Parser mParser = Parser.builder().build();
126
127
  /**
128
   * TODO: #59 -- Replace with generic interface; provide Markdown/XML
129
   * implementations.
130
   */
131
  private static final class TextVisitor {
132
    private final NodeVisitor mVisitor = new NodeVisitor( new VisitHandler<>(
133
      com.vladsch.flexmark.ast.Text.class, this::visit )
134
    );
135
136
    private final SpellCheckListener mConsumer;
137
138
    public TextVisitor( final SpellCheckListener consumer ) {
139
      mConsumer = consumer;
140
    }
141
142
    private void visit( final com.vladsch.flexmark.util.ast.Node node ) {
143
      if( node instanceof com.vladsch.flexmark.ast.Text ) {
144
        mConsumer.accept( node.getChars().toString(),
145
                          node.getStartOffset(),
146
                          node.getEndOffset() );
147
      }
148
149
      mVisitor.visitChildren( node );
150
    }
151
  }
152
}
1153
A src/main/java/com/keenwrite/spelling/impl/package-info.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
3
/**
4
 * This package contains classes for spell checking implementations.
5
 */
6
package com.keenwrite.spelling.impl;
17
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.;
6
import com.keenwrite.import com.keenwrite.util.BoundedCachte.port java// Users may opt to keep these files around for debugging purposes.
7
        if( autoclean() ) {
8
    }Answers whether logs and other files should be deleted upon error. The
9
   * log files are useful for debugging.
10
   *
11
   * @retuto delete generated files.
12
   */
13
  private boolean autocleanBooleanCLEAN );
14
  }
15
}
116
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
A src/main/java/com/keenwrite/ui/actions/Action.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.actions;
3
4
import com.keenwrite.Messages;
5
import com.keenwrite.util.GenericBuilder;
6
import constantsui.fonts.IconFactory.createGraphicStringcreateGraphic// Do not display mnemonic accelerator character in tooltip text.
7
    // The accelerator key will still be available, this is display-only.
8
    tooltip = tooltip.replace( "_", "" );tton( null, createGraphic( mIcon ) )// If there's no icon associated with the icon key name, don't attempt
9
      // to create a graphic for the icon, because it won't exist.
10
      final var iconNam      mIcon = iconKey.equals( iconName ) ? "" : iconName;
11
  }
12
}
113
A src/main/java/com/keenwrite/ui/actions/ApplicationActions.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.actions;
3
4
import com.keenwrite.ExportFormat;
5
import com.keenwrite.MainPane;
6
import com.keenwrite.MainScene;
7
import com.keenwrite.editors.TextDefinition;
8
import com.keenwrite.editors.TextEditor;
9
import com.keenwrite.editors.markdown.HyperlinkModel;
10
import com.keenwrite.editors.markdown.LinkVisitor;
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.keenwrite.util.AlphanumComparator;
25
import com.vladsch.flexmark.ast.Link;
26
import javafx.concurrent.Task;
27
import javafx.scene.control.Alert;
28
import javafx.scene.control.Dialog;
29
import javafx.stage.Window;
30
import javafx.stage.WindowEvent;
31
32
import java.io.File;
33
import java.io.IOException;
34
import java.nio.file.Path;
35
import java.util.ArrayList;
36
import java.util.List;
37
import java.util.Optional;
38
import java.util.concurrent.ExecutorService;
39
40
import static com.keenwrite.Bootstrap.*;
41
import static com.keenwrite.ExportFormat.*;
42
import static com.keenwrite.Messages.get;
43
import static com.keenwrite.constants.GraphicsConstants.ICON_DIALOG_NODE;
44
import static com.keenwrite.events.StatusEvent.clue;
45
import static com.keenwrite.preferences.WorkspaceKeys.KEY_TYPESET_CONTEXT_THEMES_PATH;
46
import static com.keenwrite.preferences.WorkspaceKeys.KEY_TYPESET_CONTEXT_THEME_SELECTION;
47
import static com.keenwrite.processors.ProcessorFactory.createProcessors;
48
import static com.keenwrite.ui.explorer.FilePickerFactory.Options;
49
import static com.keenwrite.ui.explorer.FilePickerFactory.Options.*;
50
import static com.keenwrite.util.FileWalker.walk;
51
import static java.nio.file.Files.readString;
52
import static java.nio.file.Files.writeString;
53
import static java.util.concurrent.Executors.newFixedThreadPool;
54
import static javafx.application.Platform.runLater;
55
import static javafx.event.Event.fireEvent;
56
import static javafx.scene.control.Alert.AlertType.INFORMATION;
57
import static javafx.stage.WindowEvent.WINDOW_CLOSE_REQUEST;
58
import static org.apache.commons.io.FilenameUtils.getExtension;
59
60
/**
61
 * Responsible for abstracting how functionality is mapped to the application.
62
 * This allows users to customize accelerator keys and will provide pluggable
63
 * functionality so that different text markup languages can change documents
64
 * using their respective syntax.
65
 */
66
@SuppressWarnings( "NonAsciiCharacters" )
67
public final class ApplicationActions {
68
  private static final ExecutorService sExecutor = newFixedThreadPool( 1 );
69
70
  private static final String STYLE_SEARCH = "search";
71
72
  /**
73
   * Sci-fi genres, which are can be longer than other genres, typically fall
74
   * below 150,000 words at 6 chars per word. This reduces re-allocations of
75
   * memory when concatenating files together when exporting novels.
76
   */
77
  private static final int DOCUMENT_LENGTH = 150_000 * 6;
78
79
  /**
80
   * When an action is executed, this is one of the recipients.
81
   */
82
  private final MainPane mMainPane;
83
84
  private final MainScene mMainScene;
85
86
  private final LogView mLogView;
87
88
  /**
89
   * Tracks finding text in the active document.
90
   */
91
  private final SearchModel mSearchModel;
92
93
  public ApplicationActions( final MainScene scene, final MainPane pane ) {
94
    mMainScene = scene;
95
    mMainPane = pane;
96
    mLogView = new LogView();
97
    mSearchModel = new SearchModel();
98
    mSearchModel.matchOffsetProperty().addListener( ( c, o, n ) -> {
99
      final var editor = getActiveTextEditor();
100
101
      // Clear highlighted areas before highlighting a new region.
102
      if( o != null ) {
103
        editor.unstylize( STYLE_SEARCH );
104
      }
105
106
      if( n != null ) {
107
        editor.moveTo( n.getStart() );
108
        editor.stylize( n, STYLE_SEARCH );
109
      }
110
    } );
111
112
    // When the active text editor changes, update the haystack.
113
    mMainPane.activeTextEditorProperty().addListener(
114
      ( c, o, n ) -> mSearchModel.search( getActiveTextEditor().getText() )
115
    );
116
  }
117
118
  public void file‿new() {
119
    getMainPane().newTextEditor();
120
  }
121
122
  public void file‿open() {
123
    pickFiles( FILE_OPEN_MULTIPLE ).ifPresent( l -> getMainPane().open( l ) );
124
  }
125
126
  public void file‿close() {
127
    getMainPane().close();
128
  }
129
130
  public void file‿close_all() {
131
    getMainPane().closeAll();
132
  }
133
134
  public void file‿save() {
135
    getMainPane().save();
136
  }
137
138
  public void file‿save_as() {
139
    pickFiles( FILE_SAVE_AS ).ifPresent( l -> getMainPane().saveAs( l ) );
140
  }
141
142
  public void file‿save_all() {
143
    getMainPane().saveAll();
144
  }
145
146
  /**
147
   * Converts the actively edited file in the given file format.
148
   *
149
   * @param format The destination file format.
150
   */
151
  private void file‿export( final ExportFormat format ) {
152
    file‿export( format, false );
153
  }
154
155
  /**
156
   * Converts one or more files into the given file format. If {@code dir}
157
   * is set to true, this will first append all files in the same directory
158
   * as the actively edited file.
159
   *
160
   * @param format The destination file format.
161
   * @param dir    Export all files in the actively edited file's directory.
162
   */
163
  private void file‿export( final ExportFormat format, final boolean dir ) {
164
    final var main = getMainPane();
165
    final var editor = main.getActiveTextEditor();
166
    final var filename = format.toExportFilename( editor.getPath() );
167
    final var selection = pickFiles( filename, FILE_EXPORT );
168
169
    selection.ifPresent( ( files ) -> {
170
      final var file = files.get( 0 );
171
      final var path = file.toPath();
172
      final var document = dir ? append( editor ) : editor.getText();
173
      final var context = main.createProcessorContext( path, format );
174
175
      final var task = new Task<Path>() {
176
        @Override
177
        protected Path call() throws Exception {
178
          final var chain = createProcessors( context );
179
          final var export = chain.apply( document );
180
181
          // Processors can export binary files. In such cases, processors
182
          // return null to prevent further processing.
183
          return export == null ? null : writeString( path, export );
184
        }
185
      };
186
187
      task.setOnSucceeded(
188
        e -> {
189
          final var result = task.getValue();
190
191
          // Binary formats must notify users of success independently.
192
          if( result != null ) {
193
            clue( "Main.status.export.success", result );
194
          }
195
        }
196
      );
197
198
      task.setOnFailed( e -> {
199
        final var ex = task.getException();
200
        clue( ex );
201
202
        if( ex instanceof TypeNotPresentException ) {
203
          fireExportFailedEvent();
204
        }
205
      } );
206
207
      sExecutor.execute( task );
208
    } );
209
  }
210
211
  /**
212
   * @param dir {@code true} means to export all files in the active file
213
   *            editor's directory; {@code false} means to export only the
214
   *            actively edited file.
215
   */
216
  private void file‿export‿pdf( final boolean dir ) {
217
    final var workspace = getWorkspace();
218
    final var themes = workspace.toFile( KEY_TYPESET_CONTEXT_THEMES_PATH );
219
    final var theme = workspace.stringProperty(
220
      KEY_TYPESET_CONTEXT_THEME_SELECTION );
221
222
    if( Typesetter.canRun() ) {
223
      // If the typesetter is installed, allow the user to select a theme. If
224
      // the themes aren't installed, a status message will appear.
225
      if( ThemePicker.choose( themes, theme ) ) {
226
        file‿export( APPLICATION_PDF, dir );
227
      }
228
    }
229
    else {
230
      fireExportFailedEvent();
231
    }
232
  }
233
234
  public void file‿export‿pdf() {
235
    file‿export‿pdf( false );
236
  }
237
238
  public void file‿export‿pdf‿dir() {
239
    file‿export‿pdf( true );
240
  }
241
242
  public void file‿export‿html_svg() {
243
    file‿export( HTML_TEX_SVG );
244
  }
245
246
  public void file‿export‿html_tex() {
247
    file‿export( HTML_TEX_DELIMITED );
248
  }
249
250
  public void file‿export‿xhtml_tex() {
251
    file‿export( XHTML_TEX );
252
  }
253
254
  public void file‿export‿markdown() {
255
    file‿export( MARKDOWN_PLAIN );
256
  }
257
258
  private void fireExportFailedEvent() {
259
    runLater( ExportFailedEvent::fireExportFailedEvent );
260
  }
261
262
  public void file‿exit() {
263
    final var window = getWindow();
264
    fireEvent( window, new WindowEvent( window, WINDOW_CLOSE_REQUEST ) );
265
  }
266
267
  public void edit‿undo() {
268
    getActiveTextEditor().undo();
269
  }
270
271
  public void edit‿redo() {
272
    getActiveTextEditor().redo();
273
  }
274
275
  public void edit‿cut() {
276
    getActiveTextEditor().cut();
277
  }
278
279
  public void edit‿copy() {
280
    getActiveTextEditor().copy();
281
  }
282
283
  public void edit‿paste() {
284
    getActiveTextEditor().paste();
285
  }
286
287
  public void edit‿select_all() {
288
    getActiveTextEditor().selectAll();
289
  }
290
291
  public void edit‿find() {
292
    final var nodes = getMainScene().getStatusBar().getLeftItems();
293
294
    if( nodes.isEmpty() ) {
295
      final var searchBar = new SearchBar();
296
297
      searchBar.matchIndexProperty().bind( mSearchModel.matchIndexProperty() );
298
      searchBar.matchCountProperty().bind( mSearchModel.matchCountProperty() );
299
300
      searchBar.setOnCancelAction( ( event ) -> {
301
        final var editor = getActiveTextEditor();
302
        nodes.remove( searchBar );
303
        editor.unstylize( STYLE_SEARCH );
304
        editor.getNode().requestFocus();
305
      } );
306
307
      searchBar.addInputListener( ( c, o, n ) -> {
308
        if( n != null && !n.isEmpty() ) {
309
          mSearchModel.search( n, getActiveTextEditor().getText() );
310
        }
311
      } );
312
313
      searchBar.setOnNextAction( ( event ) -> edit‿find_next() );
314
      searchBar.setOnPrevAction( ( event ) -> edit‿find_prev() );
315
316
      nodes.add( searchBar );
317
      searchBar.requestFocus();
318
    }
319
    else {
320
      nodes.clear();
321
    }
322
  }
323
324
  public void edit‿find_next() {
325
    mSearchModel.advance();
326
  }
327
328
  public void edit‿find_prev() {
329
    mSearchModel.retreat();
330
  }
331
332
  public void edit‿preferences() {
333
    try {
334
      new PreferencesController( getWorkspace() ).show();
335
    } catch( final Exception ex ) {
336
      clue( ex );
337
    }
338
  }
339
340
  public void format‿bold() {
341
    getActiveTextEditor().bold();
342
  }
343
344
  public void format‿italic() {
345
    getActiveTextEditor().italic();
346
  }
347
348
  public void format‿monospace() {
349
    getActiveTextEditor().monospace();
350
  }
351
352
  public void format‿superscript() {
353
    getActiveTextEditor().superscript();
354
  }
355
356
  public void format‿subscript() {
357
    getActiveTextEditor().subscript();
358
  }
359
360
  public void format‿strikethrough() {
361
    getActiveTextEditor().strikethrough();
362
  }
363
364
  public void insert‿blockquote() {
365
    getActiveTextEditor().blockquote();
366
  }
367
368
  public void insert‿code() {
369
    getActiveTextEditor().code();
370
  }
371
372
  public void insert‿fenced_code_block() {
373
    getActiveTextEditor().fencedCodeBlock();
374
  }
375
376
  public void insert‿link() {
377
    insertObject( createLinkDialog() );
378
  }
379
380
  public void insert‿image() {
381
    insertObject( createImageDialog() );
382
  }
383
384
  private void insertObject( final Dialog<String> dialog ) {
385
    final var textArea = getActiveTextEditor().getTextArea();
386
    dialog.showAndWait().ifPresent( textArea::replaceSelection );
387
  }
388
389
  private Dialog<String> createLinkDialog() {
390
    return new LinkDialog( getWindow(), createHyperlinkModel() );
391
  }
392
393
  private Dialog<String> createImageDialog() {
394
    final var path = getActiveTextEditor().getPath();
395
    final var parentDir = path.getParent();
396
    return new ImageDialog( getWindow(), parentDir );
397
  }
398
399
  /**
400
   * Returns one of: selected text, word under cursor, or parsed hyperlink from
401
   * the Markdown AST.
402
   *
403
   * @return An instance containing the link URL and display text.
404
   */
405
  private HyperlinkModel createHyperlinkModel() {
406
    final var context = getMainPane().createProcessorContext();
407
    final var editor = getActiveTextEditor();
408
    final var textArea = editor.getTextArea();
409
    final var selectedText = textArea.getSelectedText();
410
411
    // Convert current paragraph to Markdown nodes.
412
    final var mp = MarkdownProcessor.create( context );
413
    final var p = textArea.getCurrentParagraph();
414
    final var paragraph = textArea.getText( p );
415
    final var node = mp.toNode( paragraph );
416
    final var visitor = new LinkVisitor( textArea.getCaretColumn() );
417
    final var link = visitor.process( node );
418
419
    if( link != null ) {
420
      textArea.selectRange( p, link.getStartOffset(), p, link.getEndOffset() );
421
    }
422
423
    return createHyperlinkModel( link, selectedText );
424
  }
425
426
  private HyperlinkModel createHyperlinkModel(
427
    final Link link, final String selection ) {
428
429
    return link == null
430
      ? new HyperlinkModel( selection, "https://localhost" )
431
      : new HyperlinkModel( link );
432
  }
433
434
  public void insert‿heading_1() {
435
    insert‿heading( 1 );
436
  }
437
438
  public void insert‿heading_2() {
439
    insert‿heading( 2 );
440
  }
441
442
  public void insert‿heading_3() {
443
    insert‿heading( 3 );
444
  }
445
446
  private void insert‿heading( final int level ) {
447
    getActiveTextEditor().heading( level );
448
  }
449
450
  public void insert‿unordered_list() {
451
    getActiveTextEditor().unorderedList();
452
  }
453
454
  public void insert‿ordered_list() {
455
    getActiveTextEditor().orderedList();
456
  }
457
458
  public void insert‿horizontal_rule() {
459
    getActiveTextEditor().horizontalRule();
460
  }
461
462
  public void definition‿create() {
463
    getActiveTextDefinition().createDefinition();
464
  }
465
466
  public void definition‿rename() {
467
    getActiveTextDefinition().renameDefinition();
468
  }
469
470
  public void definition‿delete() {
471
    getActiveTextDefinition().deleteDefinitions();
472
  }
473
474
  public void definition‿autoinsert() {
475
    getMainPane().autoinsert();
476
  }
477
478
  public void view‿refresh() {
479
    getMainPane().viewRefresh();
480
  }
481
482
  public void view‿preview() {
483
    getMainPane().viewPreview();
484
  }
485
486
  public void view‿outline() {
487
    getMainPane().viewOutline();
488
  }
489
490
  public void view‿files() { getMainPane().viewFiles(); }
491
492
  public void view‿statistics() {
493
    getMainPane().viewStatistics();
494
  }
495
496
  public void view‿menubar() {
497
    getMainScene().toggleMenuBar();
498
  }
499
500
  public void view‿toolbar() {
501
    getMainScene().toggleToolBar();
502
  }
503
504
  public void view‿statusbar() {
505
    getMainScene().toggleStatusBar();
506
  }
507
508
  public void view‿log() {
509
    mLogView.view();
510
  }
511
512
  public void help‿about() {
513
    final var alert = new Alert( INFORMATION );
514
    final var prefix = "Dialog.about.";
515
    alert.setTitle( get( prefix + "title", APP_TITLE ) );
516
    alert.setHeaderText( get( prefix + "header", APP_TITLE ) );
517
    alert.setContentText( get( prefix + "content", APP_YEAR, APP_VERSION ) );
518
    alert.setGraphic( ICON_DIALOG_NODE );
519
    alert.initOwner( getWindow() );
520
    alert.showAndWait();
521
  }
522
523
  /**
524
   * Concatenates all the files in the same directory as the given file into
525
   * a string. The extension is determined by the given file name pattern; the
526
   * order files are concatenated is based on their numeric sort order (this
527
   * avoids lexicographic sorting).
528
   * <p>
529
   * If the parent path to the file being edited in the text editor cannot
530
   * be found then this will return the editor's text, without iterating through
531
   * the parent directory. (Should never happen, but who knows?)
532
   * </p>
533
   * <p>
534
   * New lines are automatically appended to separate each file.
535
   * </p>
536
   *
537
   * @param editor The text editor containing
538
   * @return All files in the same directory as the file being edited
539
   * concatenated into a single string.
540
   */
541
  private String append( final TextEditor editor ) {
542
    final var pattern = editor.getPath();
543
    final var parent = pattern.getParent();
544
545
    // Short-circuit because nothing else can be done.
546
    if( parent == null ) {
547
      clue( "Main.status.export.concat.parent", pattern );
548
      return editor.getText();
549
    }
550
551
    final var filename = pattern.getFileName().toString();
552
    final var extension = getExtension( filename );
553
554
    if( extension == null || extension.isBlank() ) {
555
      clue( "Main.status.export.concat.extension", filename );
556
      return editor.getText();
557
    }
558
559
    try {
560
      final var glob = "**/*." + extension;
561
      final ArrayList<Path> files = new ArrayList<>();
562
      walk( parent, glob, files::add );
563
      files.sort( new AlphanumComparator<>() );
564
565
      final var text = new StringBuilder( DOCUMENT_LENGTH );
566
567
      files.forEach( ( file ) -> {
568
        try {
569
          clue( "Main.status.export.concat", file );
570
          text.append( readString( file ) );
571
        } catch( final IOException ex ) {
572
          clue( "Main.status.export.concat.io", file );
573
        }
574
      } );
575
576
      return text.toString();
577
    } catch( final Throwable t ) {
578
      clue( t );
579
      return editor.getText();
580
    }
581
  }
582
583
  private Optional<List<File>> pickFiles( final Options... options ) {
584
    return createPicker( options ).choose();
585
  }
586
587
  private Optional<List<File>> pickFiles(
588
    final File filename, final Options... options ) {
589
    final var picker = createPicker( options );
590
    picker.setInitialFilename( filename );
591
    return picker.choose();
592
  }
593
594
  private FilePicker createPicker( final Options... options ) {
595
    final var factory = new FilePickerFactory( getWorkspace() );
596
    return factory.createModal( getWindow(), options );
597
  }
598
599
  private TextEditor getActiveTextEditor() {
600
    return getMainPane().getActiveTextEditor();
601
  }
602
603
  private TextDefinition getActiveTextDefinition() {
604
    return getMainPane().getActiveTextDefinition();
605
  }
606
607
  private MainScene getMainScene() {
608
    return mMainScene;
609
  }
610
611
  private MainPane getMainPane() {
612
    return mMainPane;
613
  }
614
615
  private Workspace getWorkspace() {
616
    return mMainPane.getWorkspace();
617
  }
618
619
  private Window getWindow() {
620
    return getMainPane().getWindow();
621
  }
622
}
1623
A src/main/java/com/keenwrite/ui/actions/ApplicationBars.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.actions;
13
4
import com.keenwrite.ui.controls.EventedStatusBar;
5
import javafx.event.ActionEvent;
6
import javafx.event.EventHandler;
7
import javafx.scene.Node;ApplicationActionApplicationActions_ACTION//e -> actions.file‿e -> actions.file‿open_ACTIONclose", e -> actions.file‿closclose_all", e -> actions.file‿close_all_ACTIONsave", e -> actions.file‿savsave_as", e -> actions.file‿save_assave_all", e -> actions.file‿save_all_ACTION", e -> {e -> actions.file‿export‿pdfpdf.dir", e -> actions.file‿export‿pdf‿e -> actions.file‿export‿e -> actions.file‿export‿html_texxhtml_tex", e -> actions.file‿export‿xhtml_texmarkdown", e -> actions.file‿export‿markdown_ACTIONit", e -> actions.file‿exit() )
8
    ),
9
   _ACTIONe -> actions.edit‿undoredo", e -> actions.edit‿_ACTIONcut", e -> actions.edit‿cucopy", e -> actions.edit‿copye -> actions.edit‿e -> actions.edit‿_ACTIONfind", e -> actions.edit‿e -> actions.edit‿e -> actions.edit‿find_prev_ACTIONe -> actions.edit‿preferences() )
10
    ),
11
   e -> actions.format‿bolde -> actions.format‿italice -> actions.format‿e -> actions.format‿supere -> actions.format‿e -> actions.format‿strikethrough() )
12
    ),
13
   e -> actions.insert‿e -> actions.insert‿code -> actions.insert‿_ACTIONlink", e -> actions.insert‿link, e -> actions.insert‿image_ACTIONe -> actions.insert‿e -> actions.insert‿e -> actions.insert‿_ACTION, e -> actions.insert‿e -> actions.insert‿horizontal_rule", e -> actions.insert‿horizontal_rule() )
14
    ),
15
   e‿_ACTIONe‿e‿rename‿delete() )
16
    ),
17
   e -> actions.view‿refresh_ACTIONe -> actions.view‿previe -> actions.view‿outline-> actions.view‿e-> actions.view‿files_ACTIONe -> actions.view‿menubare -> actions.view‿toolbare -> actions.view‿_ACTIONlog", e -> actions.view‿log() )
18
    ),
19
   e -> actions.help‿about() )
20
    ) );
21
    //@formatter:on_ACTION_ACTION_ACTION_ACTION_ACTION_ACTION_ACTION
A src/main/java/com/keenwrite/ui/actions/FileChooserCommand.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.actions;
13
4
import com.keenwrite.Messages;
5
import com.keenwrite.io.FileType;
6
import com.keenwrite.service.Settings;
7
import javafx.beans.property.Property;
8
constants
A src/main/java/com/keenwrite/ui/actions/MenuAction.java
1
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved.
A src/main/java/com/keenwrite/ui/actions/SeparatorAction.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.actions;
3
4
import javafx.scene.Node;
5
import javafx.scene.control.*;
16
7
/**
8
 * Represents a {@link MenuBar} or {@link ToolBar} action that has no
9
 * operatiofinal
A src/main/java/com/keenwrite/ui/actions/package-info.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
3
/**
4
 * This package contains classes that define commands as executable actions.
5
 */
6
package com.keenwrite.ui.actions;
17
A src/main/java/com/keenwrite/ui/adapters/DocumentAdapter.java
1
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved.events.StatusEvent
A src/main/java/com/keenwrite/ui/adapters/ReplacedElementAdapter.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.adapters;
3
4
import org.w3c.dom.Element;
5
import org.xhtmlrenderer.extend.ReplacedElementFactory;
6
import org.xhtmlrenderer.simple.extend.FormSubmissionListener;
7
8
/**
9
 * Allows subclasses to implement only specific events of interest.
10
 */
11
public abstract class ReplacedElementAdapter implements ReplacedElementFactory {
12
  @Override
13
  public void reset() {
14
  }
15
16
  @Override
17
  public void remove( final Element e ) {
18
  }
19
20
  @Override
21
  public void setFormSubmissionListener(
22
      final FormSubmissionListener listener ) {
23
  }
24
}
125
A src/main/java/com/keenwrite/ui/controls/BrowseButton.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.controls;
3
4
import com.keenwrite.Messages;
5
import javafx.event.ActionEvent;
6
import javafx.scene.control.Button;
7
import javafx.stage.DirectoryChooser;
8
9
import java.io.File;
10
import java.util.function.Consumer;
11
12
import static com.keenwrite.ui.fonts.IconFactory.createGraphic;
13
import static org.controlsfx.glyphfont.FontAwesome.Glyph.FILE_ALT;
14
15
/**
16
 * Responsible for browsing directories.
17
 */
18
public class BrowseButton extends Button {
19
  /**
20
   * Initial directory.
21
   */
22
  private final File mDirectory;
23
24
  /**
25
   * Called when the user accepts a directory.
26
   */
27
  private final Consumer<File> mConsumer;
28
29
  public BrowseButton( final File directory, final Consumer<File> consumer ) {
30
    assert directory != null;
31
    assert consumer != null;
32
33
    mDirectory = directory;
34
    mConsumer = consumer;
35
36
    setGraphic( createGraphic( FILE_ALT ) );
37
    setOnAction( this::browse );
38
  }
39
40
  public void browse( final ActionEvent ignored ) {
41
    final var chooser = new DirectoryChooser();
42
    chooser.setTitle( Messages.get( "BrowseDirectoryButton.chooser.title" ) );
43
    chooser.setInitialDirectory( mDirectory );
44
45
    final var result = chooser.showDialog( getScene().getWindow() );
46
47
    if( result != null ) {
48
      mConsumer.accept( result );
49
    }
50
  }
51
}
152
A src/main/java/com/keenwrite/ui/controls/BrowseFileButton.java
1
/*
2
 * Copyright 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
package com.keenwrite.ui.controls;
29
30
import com.keenwrite.Messages;
31
import javafx.beans.property.ObjectProperty;
32
import javafx.beans.property.SimpleObjectProperty;
33
import javafx.event.ActionEvent;
34
import javafx.scene.control.Button;
35
import javafx.scene.control.Tooltip;
36
import javafx.scene.input.KeyCode;
37
import javafx.scene.input.KeyEvent;
38
import javafx.stage.FileChooser;
39
import javafx.stage.FileChooser.ExtensionFilter;
40
41
import java.io.File;
42
import java.nio.file.Path;
43
import java.util.ArrayList;
44
import java.util.List;
45
46
import static com.keenwrite.ui.fonts.IconFactory.createGraphic;
47
import static org.controlsfx.glyphfont.FontAwesome.Glyph.FILE_ALT;
48
49
/**
50
 * Button that opens a file chooser to select a local file for a URL.
51
 */
52
public class BrowseFileButton extends Button {
53
54
  private final List<ExtensionFilter> mExtensionFilters = new ArrayList<>();
55
  private final ObjectProperty<Path> mBasePath = new SimpleObjectProperty<>();
56
  private final ObjectProperty<String> mUrl = new SimpleObjectProperty<>();
57
58
  public BrowseFileButton() {
59
    setGraphic( createGraphic( FILE_ALT ) );
60
    setTooltip( new Tooltip( Messages.get( "BrowseFileButton.tooltip" ) ) );
61
    setOnAction( this::browse );
62
63
    disableProperty().bind( mBasePath.isNull() );
64
65
    // workaround for a JavaFX bug:
66
    //   avoid closing the dialog that contains this control when the user
67
    //   closes the FileChooser or DirectoryChooser using the ESC key
68
    addEventHandler( KeyEvent.KEY_RELEASED, e -> {
69
      if( e.getCode() == KeyCode.ESCAPE ) {
70
        e.consume();
71
      }
72
    } );
73
  }
74
75
  public void addExtensionFilter( ExtensionFilter extensionFilter ) {
76
    mExtensionFilters.add( extensionFilter );
77
  }
78
79
  public ObjectProperty<String> urlProperty() {
80
    return mUrl;
81
  }
82
83
  private void browse( ActionEvent e ) {
84
    var fileChooser = new FileChooser();
85
    fileChooser.setTitle( Messages.get( "BrowseFileButton.chooser.title" ) );
86
    fileChooser.getExtensionFilters().addAll( mExtensionFilters );
87
    fileChooser.getExtensionFilters()
88
               .add( new ExtensionFilter( Messages.get(
89
                   "BrowseFileButton.chooser.allFilesFilter" ), "*.*" ) );
90
    fileChooser.setInitialDirectory( getInitialDirectory() );
91
    var result = fileChooser.showOpenDialog( getScene().getWindow() );
92
    if( result != null ) {
93
      updateUrl( result );
94
    }
95
  }
96
97
  private File getInitialDirectory() {
98
    //TODO build initial directory based on current value of 'url' property
99
    return getBasePath().toFile();
100
  }
101
102
  private void updateUrl( File file ) {
103
    String newUrl;
104
    try {
105
      newUrl = getBasePath().relativize( file.toPath() ).toString();
106
    } catch( final Exception ex ) {
107
      newUrl = file.toString();
108
    }
109
    mUrl.set( newUrl.replace( '\\', '/' ) );
110
  }
111
112
  public void setBasePath( Path basePath ) {
113
    this.mBasePath.set( basePath );
114
  }
115
116
  private Path getBasePath() {
117
    return mBasePath.get();
118
  }
119
}
1120
A src/main/java/com/keenwrite/ui/controls/EscapeTextField.java
1
1
/*
2
 * Copyright 2020 Karl Tauber and White Magic Software, Ltd.
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 RedistM
A src/main/java/com/keenwrite/ui/controls/EventedStatusBar.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.controls;
3
4
import com.keenwrite.events.StatusEvent;
5
import org.controlsfx.control.StatusBar;
6
import org.greenrobot.eventbus.Subscribe;
17
8
import static comtoString
A src/main/java/com/keenwrite/ui/controls/SearchBar.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.controls;
13
4
import javafx.beans*ui.fonts.IconFactory.createGraphicimport static.VERTICAL;
5
import static javafx.scene.layout.Priority.ALWAYSLabel mMatches = new LabelmFind,
6
mButtonNext,
7
mButtonPrev,
8
mMatches,
9
return createGraphic(
A src/main/java/com/keenwrite/ui/dialogs/AbstractDialog.java
1
1
/* Copyright 2017-2021 White Magic Software, Ltd. -- All rights reserved.Stageconstants
A src/main/java/com/keenwrite/ui/dialogs/ImageDialog.java
1
1
/*
2
 * Copyright 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 RM
A src/main/java/com/keenwrite/ui/dialogs/ImageDialog.jfd
1
JFDML JFormDesigner: "9.9.9.9.9999" Java: "1.8.0_66" encoding: "UTF-8"
12
3
new FormModel {
4
	"i18n.bundlePackage": "com.scrivendor"
5
	"i18n.bundleName": "messages"
6
	"i18n.autoExternalize": true
7
	"i18n.keyPrefix": "ImageDialog"
8
	contentType: "form/javafx"
9
	root:ImageImage2 1Image2 1Image2
A src/main/java/com/keenwrite/ui/dialogs/LinkDialog.java
1
1
/*
2
 * Copyright 2016 Karl Tauber and White Magic Software, Ltd.
3
 *
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions are met:
8
 *
9
 *  o RM
A src/main/java/com/keenwrite/ui/dialogs/LinkDialog.jfd
1
JFDML JFormDesigner: "9.9.9.9.9999" Java: "1.8.0_66" encoding: "UTF-8"
2
3
new FormModel {
4
	"i18n.bundlePackage": "com.scrivendor"
5
	"i18n.bundleName": "messages"
6
	"i18n.autoExternalize": true
7
	"i18n.keyPrefix": "LinkDialog"
8
	contentType: "form/javafx"
9
	root: new FormRoot {
10
		add( new FormContainer( "org.tbee.javafx.scene.layout.fxml.MigPane", new FormLayoutManager( class org.tbee.javafx.scene.layout.fxml.MigPane ) {
11
			"$layoutConstraints": ""
12
			"$columnConstraints": "[shrink 0,fill][300,grow,fill][fill][fill]"
13
			"$rowConstraints": "[][][][]"
14
		} ) {
15
			name: "pane"
16
			add( new FormComponent( "javafx.scene.control.Label" ) {
17
				name: "urlLabel"
18
				"text": new FormMessage( null, "LinkDialog.urlLabel.text" )
19
				auxiliary() {
20
					"JavaCodeGenerator.variableLocal": true
21
				}
22
			}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
23
				"value": "cell 0 0"
24
			} )
25
			add( new FormComponent( "com.scrivendor.controls.EscapeTextField" ) {
26
				name: "urlField"
27
				"escapeCharacters": "()"
28
				"text": "http://yourlink.com"
29
				"promptText": "http://yourlink.com"
30
			}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
31
				"value": "cell 1 0"
32
			} )
33
			add( new FormComponent( "com.scrivendor.controls.BrowseDirectoryButton" ) {
34
				name: "linkBrowseDirectoyButton"
35
			}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
36
				"value": "cell 2 0"
37
			} )
38
			add( new FormComponent( "com.scrivendor.controls.BrowseFileButton" ) {
39
				name: "linkBrowseFileButton"
40
			}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
41
				"value": "cell 3 0"
42
			} )
43
			add( new FormComponent( "javafx.scene.control.Label" ) {
44
				name: "textLabel"
45
				"text": new FormMessage( null, "LinkDialog.textLabel.text" )
46
				auxiliary() {
47
					"JavaCodeGenerator.variableLocal": true
48
				}
49
			}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
50
				"value": "cell 0 1"
51
			} )
52
			add( new FormComponent( "com.scrivendor.controls.EscapeTextField" ) {
53
				name: "textField"
54
				"escapeCharacters": "[]"
55
			}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
56
				"value": "cell 1 1 3 1"
57
			} )
58
			add( new FormComponent( "javafx.scene.control.Label" ) {
59
				name: "titleLabel"
60
				"text": new FormMessage( null, "LinkDialog.titleLabel.text" )
61
				auxiliary() {
62
					"JavaCodeGenerator.variableLocal": true
63
				}
64
			}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
65
				"value": "cell 0 2"
66
			} )
67
			add( new FormComponent( "com.scrivendor.controls.EscapeTextField" ) {
68
				name: "titleField"
69
			}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
70
				"value": "cell 1 2 3 1"
71
			} )
72
			add( new FormComponent( "javafx.scene.control.Label" ) {
73
				name: "previewLabel"
74
				"text": new FormMessage( null, "LinkDialog.previewLabel.text" )
75
				auxiliary() {
76
					"JavaCodeGenerator.variableLocal": true
77
				}
78
			}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
79
				"value": "cell 0 3"
80
			} )
81
			add( new FormComponent( "javafx.scene.control.Label" ) {
82
				name: "previewField"
83
			}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
84
				"value": "cell 1 3 3 1"
85
			} )
86
		}, new FormLayoutConstraints( null ) {
87
			"location": new javafx.geometry.Point2D( 0.0, 0.0 )
88
			"size": new javafx.geometry.Dimension2D( 500.0, 300.0 )
89
		} )
90
	}
91
}
192
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;
13
4
import com.keenwrite.util.FileWalker;
5
import com.keenwrite.util.ResourceWalker;
6
import javafx.beans.property.StringProperty;
7
import javafx.scene.con
8
    final var window =;
9
    if( window instanceof Stage ) {
10
      ((Stage) window).getIcons().add( ICON_DIALOG
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;
13
4
import com.io7m.jwheatsheaf.ui.JWFileChoosers;
5
import com.keenwrite.preferences.Workspace;
6
import javafx.beans.property.ObjectProperty;
7
import{
8
             action = CREATE;
9
          }{
10
             action = CREATE;
11
          }SINGSING
A src/main/java/com/keenwrite/ui/explorer/FilesView.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.explorer;
3
4
import com.keenwrite.ui.controls.BrowseButton;
5
import javafx.beans.property.*;
6
import javafx.collections.ObservableList;
7
import javafx.collections.transformation.SortedList;
8
import javafx.scene.control.*;
9
import javafx.scene.layout.BorderPane;
10
import javafx.scene.layout.HBox;
11
import javafx.stage.FileChooser;
12
import javafx.util.Callback;
13
14
import java.io.File;
15
import java.io.IOException;
16
import java.nio.file.Path;
17
import java.nio.file.Paths;
18
import java.time.Instant;
19
import java.time.format.DateTimeFormatter;
20
import java.util.List;
21
import java.util.Locale;
22
import java.util.Optional;
23
24
import static com.keenwrite.constants.Constants.UI_CONTROL_SPACING;
25
import static com.keenwrite.events.FileOpenEvent.fireFileOpenEvent;
26
import static com.keenwrite.events.StatusEvent.clue;
27
import static com.keenwrite.ui.fonts.IconFactory.createFileIcon;
28
import static java.nio.file.Files.size;
29
import static java.time.Instant.ofEpochMilli;
30
import static java.time.ZoneId.systemDefault;
31
import static java.time.format.DateTimeFormatter.ofPattern;
32
import static java.util.Comparator.comparing;
33
import static javafx.collections.FXCollections.observableArrayList;
34
import static javafx.scene.control.TableView.CONSTRAINED_RESIZE_POLICY;
35
import static javafx.scene.input.KeyCode.ENTER;
36
import static javafx.scene.layout.Priority.ALWAYS;
37
import static org.apache.commons.io.FilenameUtils.getExtension;
38
39
/**
40
 * Responsible for browsing files.
41
 */
42
public class FilesView extends BorderPane implements FilePicker {
43
  /**
44
   * When this directory changes, the input field will update accordingly.
45
   */
46
  private final ObjectProperty<File> mDirectory;
47
48
  /**
49
   * Data model for the file list shown in tabular format.
50
   */
51
  private final ObservableList<PathEntry> mItems = observableArrayList();
52
53
  /**
54
   * Used to format a file's date string from a {@code long} value.
55
   */
56
  private final DateTimeFormatter mDateFormatter;
57
58
  /**
59
   * Used to format a file's time string from a {@code long} value.
60
   */
61
  private final DateTimeFormatter mTimeFormatter;
62
63
  /**
64
   * Constructs a new view of a directory, listing all the files contained
65
   * therein. This will update the recent directory so that it will be
66
   * restored upon restart.
67
   *
68
   * @param recent Contains the initial (recent) directory.
69
   * @param locale Contains the language settings.
70
   */
71
  public FilesView(
72
    final ObjectProperty<File> recent, final Locale locale ) {
73
    mDirectory = recent;
74
    mDateFormatter = createFormatter( "yyyy-MMM-dd", locale );
75
    mTimeFormatter = createFormatter( "HH:mm:ss", locale );
76
77
    final var browse = createDirectoryChooser();
78
    final var table = createFileTable();
79
80
    final var sortedItems = new SortedList<>( mItems );
81
    sortedItems.comparatorProperty().bind( table.comparatorProperty() );
82
    table.setItems( sortedItems );
83
84
    setTop( browse );
85
    setCenter( table );
86
87
    mDirectory.addListener( ( c, o, n ) -> updateListing( n ) );
88
    updateListing( mDirectory.get() );
89
  }
90
91
  @Override
92
  public Optional<List<File>> choose() {
93
    return Optional.empty();
94
  }
95
96
  private void updateListing( final File directory ) {
97
    if( directory != null ) {
98
      mItems.clear();
99
100
      try {
101
        if( directory.getParent() != null ) {
102
          // Allow traversal to parent-directory.
103
          mItems.add( pathEntry( Paths.get( ".." ) ) );
104
        }
105
106
        for( final var f : directory.list() ) {
107
          if( !f.startsWith( "." ) ) {
108
            mItems.add( pathEntry( Paths.get( directory.toString(), f ) ) );
109
          }
110
        }
111
      } catch( final Exception ex ) {
112
        clue( ex );
113
      }
114
    }
115
  }
116
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
   */
123
  private HBox createDirectoryChooser() {
124
    final var dirProperty = directoryProperty();
125
    final var directory = dirProperty.get();
126
    final var hbox = new HBox();
127
    final var field = new TextField();
128
129
    mDirectory.addListener( ( c, o, n ) -> {
130
      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
      }
137
    } );
138
139
    final var button = new BrowseButton( directory, mDirectory::set );
140
141
    hbox.getChildren().add( button );
142
    hbox.getChildren().add( field );
143
    hbox.setSpacing( UI_CONTROL_SPACING );
144
    HBox.setHgrow( field, ALWAYS );
145
146
    return hbox;
147
  }
148
149
  @SuppressWarnings( "unchecked" )
150
  private TableView<FilesView.PathEntry> createFileTable() {
151
    final var style = "-fx-alignment: BASELINE_LEFT;";
152
    final var table = new TableView<FilesView.PathEntry>();
153
    table.setColumnResizePolicy( CONSTRAINED_RESIZE_POLICY );
154
155
    table.setRowFactory( tv -> {
156
      final var row = new TableRow<PathEntry>();
157
158
      row.setOnMouseClicked( event -> {
159
        if( event.getClickCount() == 2 && !row.isEmpty() ) {
160
          final var entry = row.getItem();
161
          final var dir = mDirectory.get();
162
          final var filename = entry.nameProperty().get();
163
          final var path = Path.of( dir.toString(), filename );
164
          final var file = path.toFile();
165
166
          if( file.isFile() ) {
167
            fireFileOpenEvent( path.toUri() );
168
          }
169
          else if( file.isDirectory() ) {
170
            mDirectory.set( path.normalize().toFile() );
171
          }
172
        }
173
      } );
174
175
      return row;
176
    } );
177
178
    final TableColumn<PathEntry, Path> colType = createColumn( "Type" );
179
    final TableColumn<PathEntry, String> colName = createColumn( "Name" );
180
    final TableColumn<PathEntry, Number> colSize = createColumn( "Size" );
181
    final TableColumn<PathEntry, String> colDate = createColumn( "Date" );
182
    final TableColumn<PathEntry, String> colTime = createColumn( "Modified" );
183
184
    colType.setCellFactory( new FileCell<>() );
185
186
    colType.setCellValueFactory( stat -> stat.getValue().typeProperty() );
187
    colName.setCellValueFactory( stat -> stat.getValue().nameProperty() );
188
    colSize.setCellValueFactory( stat -> stat.getValue().sizeProperty() );
189
    colDate.setCellValueFactory( stat -> stat.getValue().dateProperty() );
190
    colTime.setCellValueFactory( stat -> stat.getValue().timeProperty() );
191
192
    colType.setStyle( style );
193
    colName.setStyle( style );
194
    colSize.setStyle( style );
195
    colDate.setStyle( style );
196
    colTime.setStyle( style );
197
198
    final var columns = table.getColumns();
199
    columns.add( colType );
200
    columns.add( colName );
201
    columns.add( colSize );
202
    columns.add( colDate );
203
    columns.add( colTime );
204
205
    table.getSortOrder().setAll( colName, colDate, colTime );
206
207
    colType.setComparator(
208
      comparing( p -> getExtension( p.getFileName().toString() ) )
209
    );
210
211
    return table;
212
  }
213
214
  public ObjectProperty<File> directoryProperty() {
215
    return mDirectory;
216
  }
217
218
  private static DateTimeFormatter createFormatter(
219
    final String format, final Locale locale ) {
220
    return ofPattern( format, locale ).withZone( systemDefault() );
221
  }
222
223
  public PathEntry pathEntry( final Path path ) throws IOException {
224
    return new PathEntry( path );
225
  }
226
227
  /**
228
   * Responsible for rendering file system objects as image icons.
229
   *
230
   * @param <T> The data model type associated with a fully qualified path.
231
   * @param <P> Simplifies swapping {@link Path} for {@link File}.
232
   */
233
  private static class FileCell<T, P extends Path> extends TableCell<T, P>
234
    implements Callback<TableColumn<T, P>, TableCell<T, P>> {
235
    @Override
236
    public TableCell<T, P> call( final TableColumn<T, P> param ) {
237
      return new TableCell<>() {
238
        @Override
239
        protected void updateItem( final P path, final boolean empty ) {
240
          super.updateItem( path, empty );
241
          setText( null );
242
243
          try {
244
            setGraphic( empty || path == null ? null : createFileIcon( path ) );
245
          } catch( final Exception ex ) {
246
            clue( ex );
247
          }
248
        }
249
      };
250
    }
251
  }
252
253
  protected final class PathEntry {
254
    private final ObjectProperty<Path> mType;
255
    private final StringProperty mName;
256
    private final LongProperty mSize;
257
    private final StringProperty mDate;
258
    private final StringProperty mTime;
259
260
    protected PathEntry( final Path path ) throws IOException {
261
      this(
262
        path,
263
        path.getFileName().toString(),
264
        size( path ),
265
        ofEpochMilli( path.toFile().lastModified() )
266
      );
267
    }
268
269
    public PathEntry(
270
      final Path type,
271
      final String name,
272
      final long size,
273
      final Instant modified ) {
274
      this(
275
        new SimpleObjectProperty<>( type ),
276
        new SimpleStringProperty( name ),
277
        new SimpleLongProperty( size ),
278
        new SimpleStringProperty( mDateFormatter.format( modified ) ),
279
        new SimpleStringProperty( mTimeFormatter.format( modified ) )
280
      );
281
    }
282
283
    private PathEntry(
284
      final ObjectProperty<Path> type,
285
      final StringProperty name,
286
      final LongProperty size,
287
      final StringProperty date,
288
      final StringProperty time ) {
289
      mType = type;
290
      mName = name;
291
      mSize = size;
292
      mDate = date;
293
      mTime = time;
294
    }
295
296
    private ObjectProperty<Path> typeProperty() {
297
      return mType;
298
    }
299
300
    private StringProperty nameProperty() {
301
      return mName;
302
    }
303
304
    private LongProperty sizeProperty() {
305
      return mSize;
306
    }
307
308
    private StringProperty dateProperty() {
309
      return mDate;
310
    }
311
312
    private StringProperty timeProperty() {
313
      return mTime;
314
    }
315
  }
316
317
  private <E, T> TableColumn<E, T> createColumn( final String key ) {
318
    return new TableColumn<>( key );
319
  }
320
}
1321
A src/main/java/com/keenwrite/ui/fonts/IconFactory.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.fonts;
3
4
import com.keenwrite.io.MediaType;
5
import com.keenwrite.io.MediaTypeExtension;
6
import javafx.scene.Node;
7
import javafx.scene.image.Image;
8
import javafx.scene.image.ImageView;
9
import org.controlsfx.glyphfont.FontAwesome;
10
import org.controlsfx.glyphfont.Glyph;
11
12
import java.awt.*;
13
import java.awt.image.BufferedImage;
14
import java.io.IOException;
15
import java.io.InputStream;
16
import java.nio.file.Path;
17
import java.nio.file.attribute.BasicFileAttributes;
18
import java.util.HashMap;
19
import java.util.Map;
20
21
import static com.keenwrite.events.StatusEvent.clue;
22
import static com.keenwrite.io.MediaTypeExtension.MEDIA_UNDEFINED;
23
import static com.keenwrite.preview.SvgRasterizer.BROKEN_IMAGE_PLACEHOLDER;
24
import static com.keenwrite.preview.SvgRasterizer.rasterize;
25
import static java.awt.Font.BOLD;
26
import static java.nio.file.Files.readAttributes;
27
import static javafx.embed.swing.SwingFXUtils.toFXImage;
28
import static org.apache.commons.io.FilenameUtils.getExtension;
29
import static org.controlsfx.glyphfont.FontAwesome.Glyph.valueOf;
30
31
/**
32
 * Responsible for creating FontAwesome glyphs and graphics.
33
 */
34
public class IconFactory {
35
  /**
36
   * File icon height, in pixels.
37
   */
38
  private static final int ICON_HEIGHT = 16;
39
40
  /**
41
   * Singleton to prevent re-loading the TTF file.
42
   */
43
  private static final FontAwesome FONT_AWESOME = new FontAwesome();
44
45
  /**
46
   * Caches file type icons encountered.
47
   */
48
  private static final Map<String, Image> ICONS = new HashMap<>();
49
50
  /**
51
   * Prevent instantiation. Use the {@link #createGraphic(String)} method to
52
   * create an icon for display.
53
   */
54
  private IconFactory() {}
55
56
  /**
57
   * Create a {@link Node} representation for the given icon name.
58
   *
59
   * @param icon Name of icon to convert to a UI object (case-insensitive).
60
   * @return A UI object suitable for display.
61
   */
62
  public static Node createGraphic( final String icon ) {
63
    assert icon != null;
64
65
    // Return a label glyph.
66
    return icon.isEmpty()
67
      ? new Glyph()
68
      : createGlyph( icon );
69
  }
70
71
  /**
72
   * Create a {@link Node} representation for the given FontAwesome glyph.
73
   *
74
   * @param glyph The glyph to convert to a {@link Node}.
75
   * @return The given glyph as a text label.
76
   */
77
  public static Node createGraphic( final FontAwesome.Glyph glyph ) {
78
    return FONT_AWESOME.create( glyph );
79
  }
80
81
  /**
82
   * Creates a suitable {@link Node} icon representation for the given file.
83
   * This will first look up the {@link MediaType} before matching based on
84
   * the file name extension.
85
   *
86
   * @param path The file to represent graphically.
87
   * @return An icon representation for the given file.
88
   */
89
  public static ImageView createFileIcon( final Path path ) throws IOException {
90
    final var attrs = readAttributes( path, BasicFileAttributes.class );
91
    final var filename = path.getFileName().toString();
92
    String extension;
93
94
    if( "..".equals( filename ) ) {
95
      extension = "folder-up";
96
    }
97
    else if( attrs.isDirectory() ) {
98
      extension = "folder";
99
    }
100
    else if( attrs.isSymbolicLink() ) {
101
      extension = "folder-link";
102
    }
103
    else {
104
      final var mediaType = MediaType.valueFrom( path );
105
      final var mte = MediaTypeExtension.valueFrom( mediaType );
106
107
      // if the file extension is not known to the app, try loading an icon
108
      // that corresponds to the extension directly.
109
      extension = mte == MEDIA_UNDEFINED
110
        ? getExtension( filename )
111
        : mte.getExtension();
112
    }
113
114
    if(extension == null) {
115
      extension = "";
116
    }
117
    else {
118
      extension = extension.toLowerCase();
119
    }
120
121
    // Each cell in the table must have a distinct parent, so the image views
122
    // cannot be reused. The underlying buffered image can be cached, though.
123
    final var image =
124
      ICONS.computeIfAbsent( extension, IconFactory::createFxImage );
125
    final var imageView = new ImageView();
126
    imageView.setPreserveRatio( true );
127
    imageView.setFitHeight( ICON_HEIGHT );
128
    imageView.setImage( image );
129
130
    return imageView;
131
  }
132
133
  private static Image createFxImage( final String extension ) {
134
    return toFXImage( createImage( extension ), null );
135
  }
136
137
  private static BufferedImage createImage( final String extension ) {
138
    try( final var icon = open( "icons/" + extension + ".svg" ) ) {
139
      if( icon == null ) {
140
        throw new IllegalArgumentException( extension );
141
      }
142
143
      return rasterize( icon );
144
    } catch( final Exception ex ) {
145
      clue( ex );
146
147
      // If the extension was unknown, fall back to a blank icon, falling
148
      // back again to a broken image if blank cannot be found (to avoid
149
      // infinite recursion).
150
      return "blank".equals( extension )
151
        ? BROKEN_IMAGE_PLACEHOLDER
152
        : createImage( "blank" );
153
    }
154
  }
155
156
  private static InputStream open( final String resource ) {
157
    return IconFactory.class.getResourceAsStream( resource );
158
  }
159
160
  public static Font getIconFont( final int size ) {
161
    return new Font( FONT_AWESOME.getName(), BOLD, size );
162
  }
163
164
  private static Node createGlyph( final String icon ) {
165
    return createGraphic( valueOf( icon.toUpperCase() ) );
166
  }
167
}
1168
A src/main/java/com/keenwrite/ui/heuristics/DocumentStatistics.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.heuristics;
3
4
import com.keenwrite.events.DocumentChangedEvent;
5
import com.keenwrite.preferences.Workspace;
6
import com.keenwrite.preview.HtmlPanel;
7
importui.heuristics.DocumentStatistics.StatEntry extends TableView<StatEntry> {
18
9
  private WordCounter mWordCounter;mWordCounter = WordCounter.create( workspace.getLocalefinal var document = event.getDocument();
10
        final var wordCount = mWordCounter.countWords(
11
          document, ( k, count ) -> {
12
            // Generate statistics for words that occur thrice or more.
13
  }
14
       wordCount );
15
      } );mWordCounter = WordCounter.create
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
A src/main/java/com/keenwrite/ui/listeners/CaretListener.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.listeners;
3
4
import com.keenwrite.Caret;
5
import com.keenwrite.editors.TextEditor;
6
import com.keenwrite.events.WordCountEvent;
7
import javafx.beans.property.ReadOnlyObjectProperty;
8
import javafx.beans.value.ChangeListener;
9
import javafx.beans.value.ObservableValue;
10
import javafx.scene.control.Label;
11
import javafx.scene.layout.VBox;
12
import org.greenrobot.eventbus.Subscribe;
13
14
import static com.keenwrite.events.Bus.register;
15
import static javafx.application.Platform.runLater;
16
import static javafx.geometry.Pos.BASELINE_CENTER;
17
18
/**
19
 * Responsible for updating the UI whenever the caret changes position.
20
 * Only one instance of {@link CaretListener} is allowed, which prevents
21
 * duplicate adds to the observable property.
22
 */
23
public class CaretListener extends VBox implements ChangeListener<Integer> {
24
25
  /**
26
   * Use an instance of {@link Label} for its built-in CSS style class.
27
   */
28
  private final Label mLineNumberText = new Label();
29
  private volatile Caret mCaret;
30
31
  /**
32
   * Approximate number of words in the document.
33
   */
34
  private volatile int mCount;
35
36
  public CaretListener( final ReadOnlyObjectProperty<TextEditor> editor ) {
37
    assert editor != null;
38
39
    setAlignment( BASELINE_CENTER );
40
    getChildren().add( mLineNumberText );
41
42
    editor.addListener( ( c, o, n ) -> {
43
      if( n != null ) {
44
        updateListener( n.getCaret() );
45
      }
46
    } );
47
48
    updateListener( editor.get().getCaret() );
49
    register( this );
50
  }
51
52
  /**
53
   * Called whenever the caret position changes.
54
   *
55
   * @param c The caret position property.
56
   * @param o The old caret position offset.
57
   * @param n The new caret position offset.
58
   */
59
  @Override
60
  public void changed(
61
    final ObservableValue<? extends Integer> c,
62
    final Integer o, final Integer n ) {
63
    updateLineNumber();
64
  }
65
66
  @Subscribe
67
  public void handle( final WordCountEvent event ) {
68
    mCount = event.getCount();
69
    updateLineNumber();
70
  }
71
72
  private void updateListener( final Caret caret ) {
73
    assert caret != null;
74
75
    final var property = caret.textOffsetProperty();
76
77
    property.removeListener( this );
78
    mCaret = caret;
79
    property.addListener( this );
80
    updateLineNumber();
81
  }
82
83
  private void updateLineNumber() {
84
    runLater(
85
      () -> mLineNumberText.setText( mCaret.toString() + " | " + mCount )
86
    );
87
  }
88
}
189
A src/main/java/com/keenwrite/ui/logging/LogView.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.logging;
13
4
import com.keenwrite.events.StatusEvent;
5
import javafx.beans.property.SimpleStringProperty;
6
import javafx.beans.property.StringProperty;
7
importconstantsconstantsloggetStage()
A src/main/java/com/keenwrite/ui/outline/DocumentOutline.java
1
package com.keenwrite.ui.outline;
2
3
import com.keenwrite.events.Bus;
4
import com.keenwrite.events.ParseHeadingEvent;
5
import javafx.Nodecontrol.TreeCell;
6
iui.fonts.IconFactory.createGraphicNodecreateGraphic( "BOOKMARK" );
7
  }
8
}
19
A src/main/java/com/keenwrite/ui/tree/AltTreeCell.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.tree;
3
4
import javafx.beans.property.Property;
5
import javafx.beans.property.SimpleStringProperty;
6
import javafx.beans.value.ChangeListener;
7
import javafx.beans.value.ObservableValue;
8
import javafx.event.EventHandler;
9
import javafx.scene.control.TextField;
10
import javafx.scene.control.cell.TextFieldTreeCell;
11
import javafx.scene.input.KeyEvent;
12
import javafx.util.StringConverter;
13
14
import static javafx.application.Platform.runLater;
15
import static javafx.scene.input.KeyCode.ENTER;
16
import static javafx.scene.input.KeyCode.TAB;
17
import static javafx.scene.input.KeyEvent.KEY_RELEASED;
18
19
/**
20
 * Responsible for enhancing the existing cell behaviour with fairly common
21
 * functionality, including commit on focus loss and Enter to commit.
22
 *
23
 * @param <T> The type of data stored by the tree.
24
 */
25
public class AltTreeCell<T> extends TextFieldTreeCell<T> {
26
  private final KeyHandler mKeyHandler = new KeyHandler();
27
  private final Property<String> mInputText = new SimpleStringProperty();
28
  private FocusListener mFocusListener;
29
30
  public AltTreeCell( final StringConverter<T> converter ) {
31
    super( converter );
32
    assert converter != null;
33
34
    // When the text field is added as the graphics context, we hook into
35
    // the changed value to get a handle on the text field. From there it is
36
    // possible to add change the keyboard and focus behaviours.
37
    graphicProperty().addListener( ( c, o, n ) -> {
38
      if( o instanceof TextField ) {
39
        o.removeEventHandler( KEY_RELEASED, mKeyHandler );
40
        o.focusedProperty().removeListener( mFocusListener );
41
      }
42
43
      if( n instanceof TextField ) {
44
        n.addEventFilter( KEY_RELEASED, mKeyHandler );
45
        final var input = (TextField) n;
46
        mInputText.bind( input.textProperty() );
47
        mFocusListener = new FocusListener( input );
48
        n.focusedProperty().addListener( mFocusListener );
49
      }
50
    } );
51
  }
52
53
  private void commitEdit() {
54
    commitEdit( getConverter().fromString( mInputText.getValue() ) );
55
  }
56
57
  /**
58
   * Responsible for accepting the text when users press the Enter or Tab key.
59
   */
60
  private class KeyHandler implements EventHandler<KeyEvent> {
61
    @Override
62
    public void handle( final KeyEvent event ) {
63
      if( event.getCode() == ENTER || event.getCode() == TAB ) {
64
        commitEdit();
65
        event.consume();
66
      }
67
    }
68
  }
69
70
  /**
71
   * Responsible for committing edits when focus is lost. This will also
72
   * deselect the input field when focus is gained so that typing text won't
73
   * overwrite the entire existing text.
74
   */
75
  private class FocusListener implements ChangeListener<Boolean> {
76
    private final TextField mInput;
77
78
    private FocusListener( final TextField input ) {
79
      mInput = input;
80
    }
81
82
    @Override
83
    public void changed(
84
      final ObservableValue<? extends Boolean> c,
85
      final Boolean endedFocus, final Boolean beganFocus ) {
86
87
      if( beganFocus ) {
88
        runLater( mInput::deselect );
89
      }
90
      else if( endedFocus ) {
91
        commitEdit();
92
      }
93
    }
94
  }
95
}
196
A src/main/java/com/keenwrite/ui/tree/AltTreeCellFactory.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.tree;
3
// <p>
4
 * TODO: #22 -- Upon refactoring variable functionality, re-instate drag & drop.
5
 * </p>}
16
A src/main/java/com/keenwrite/ui/tree/AltTreeView.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.tree;
3
4
import javafx.scene.control.TreeItem;
5
import javafx.scene.control.TreeView;
6
import javafx.util.StringConverter;
7
8
/**
9
 * Responsible for allowing users to edit items in the tree as well as
10
 * drag and drop. The goal is to be a drop-in replacement for the regular
11
 * JavaFX {@link TreeView}, which does not offer editing and moving {@link
12
 * TreeItem} instances.
13
 *
14
 * @param <T> The type of data to edit.
15
 */
16
public class AltTreeView<T> extends TreeView<T> {
17
  public AltTreeView(
18
    final TreeItem<T> root, final StringConverter<T> converter ) {
19
    super( root );
20
21
    setEditable( true );
22
    setCellFactory( new AltTreeCellFactory<>( converter ) );
23
    setShowRoot( false );
24
25
    // When focus is lost, clear the selected item only when not editing.
26
    focusedProperty().addListener( ( c, o, n ) -> {
27
      if( o && getEditingItem() == null ) {
28
        getSelectionModel().clearSelection();
29
      }
30
    } );
31
  }
32
}
133
A src/main/java/com/keenwrite/ui/tree/TreeItemConverter.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.tree;
3
4
import javafx.util.StringConverter;
5
6
/**
7
 * Responsible for converting objects to and from string instances. The
8
 * tree items contain only strings, so this effectively is a string-to-string
9
 * converter, which allows the implementation to retain its generics.
10
 */
11
public class TreeItemConverter extends StringConverter<String> {
12
13
  @Override
14
  public String toString( final String object ) {
15
    return sanitize( object );
16
  }
17
18
  @Override
19
  public String fromString( final String string ) {
20
    return sanitize( string );
21
  }
22
23
  private String sanitize( final String string ) {
24
    return string == null ? "" : string;
25
  }
26
}
127
A src/main/java/com/keenwrite/util/AlphanumComparator.java
1
/*
2
 * The Alphanum Algorithm is an improved sorting algorithm for strings
3
 * containing numbers. Rather than sort numbers in ASCII order like
4
 * a standard sort, this algorithm sorts numbers in numeric order.
5
 *
6
 * The Alphanum Algorithm is discussed at http://www.DaveKoelle.com
7
 *
8
 * Released under the MIT License - https://opensource.org/licenses/MIT
9
 *
10
 * Copyright 2007-2017 David Koelle
11
 *
12
 * Permission is hereby granted, free of charge, to any person obtaining
13
 * a copy of this software and associated documentation files (the "Software"),
14
 * to deal in the Software without restriction, including without limitation
15
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16
 * and/or sell copies of the Software, and to permit persons to whom the
17
 * Software is furnished to do so, subject to the following conditions:
18
 *
19
 * The above copyright notice and this permission notice shall be included
20
 * in all copies or substantial portions of the Software.
21
 *
22
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
26
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
27
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
28
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
29
 */
30
package com.keenwrite.util;
31
32
import java.util.Comparator;
33
34
import static java.lang.Character.isDigit;
35
36
/**
37
 * Responsible for sorting lists that may contain numeric values. Usage:
38
 * <pre>
39
 *   Collections.sort(list, new AlphanumComparator());
40
 * </pre>
41
 * <p>
42
 * Where "list" is the list to sort alphanumerically, not lexicographically.
43
 * </p>
44
 */
45
public final class AlphanumComparator<T> implements Comparator<T> {
46
  /**
47
   * Returns a chunk of text that is continuous with respect to digits or
48
   * non-digits.
49
   *
50
   * @param s      The string to compare.
51
   * @param length The string length, for improved efficiency.
52
   * @param marker The current index into a subset of the given string.
53
   * @return The substring {@code s} that is a continuous text chunk of the
54
   * same character type.
55
   */
56
  private StringBuilder chunk( final String s, final int length, int marker ) {
57
    assert s != null;
58
    assert length >= 0;
59
    assert marker < length;
60
61
    // Prevent any possible memory re-allocations by using the length.
62
    final var chunk = new StringBuilder( length );
63
    var c = s.charAt( marker );
64
    final var chunkType = isDigit( c );
65
66
    // While the character at the current position is the same type (numeric or
67
    // alphabetic), append the character to the current chunk.
68
    while( marker < length &&
69
      isDigit( c = s.charAt( marker++ ) ) == chunkType ) {
70
      chunk.append( c );
71
    }
72
73
    return chunk;
74
  }
75
76
  /**
77
   * Performs an alphanumeric comparison of two strings, sorting numerically
78
   * first when numbers are found within the string. If either argument is
79
   * {@code null}, this will return zero.
80
   *
81
   * @param o1 The object to compare against {@code s2}, converted to string.
82
   * @param o2 The object to compare against {@code s1}, converted to string.
83
   * @return a negative integer, zero, or a positive integer if the first
84
   * argument is less than, equal to, or greater than the second, respectively.
85
   */
86
  @Override
87
  public int compare( final T o1, final T o2 ) {
88
    if( o1 == null || o2 == null ) {
89
      return 0;
90
    }
91
92
    final var s1 = o1.toString();
93
    final var s2 = o2.toString();
94
    final var s1Length = s1.length();
95
    final var s2Length = s2.length();
96
97
    var thisMarker = 0;
98
    var thatMarker = 0;
99
100
    while( thisMarker < s1Length && thatMarker < s2Length ) {
101
      final var thisChunk = chunk( s1, s1Length, thisMarker );
102
      final var thisChunkLength = thisChunk.length();
103
      thisMarker += thisChunkLength;
104
      final var thatChunk = chunk( s2, s2Length, thatMarker );
105
      final var thatChunkLength = thatChunk.length();
106
      thatMarker += thatChunkLength;
107
108
      // If both chunks contain numeric characters, sort them numerically
109
      int result;
110
111
      if( isDigit( thisChunk.charAt( 0 ) ) &&
112
        isDigit( thatChunk.charAt( 0 ) ) ) {
113
        // If equal, the first different number counts
114
        if( (result = thisChunkLength - thatChunkLength) == 0 ) {
115
          for( var i = 0; i < thisChunkLength; i++ ) {
116
            if( (result = thisChunk.charAt( i ) - thatChunk.charAt( i )) != 0 ) {
117
              return result;
118
            }
119
          }
120
        }
121
      }
122
      else {
123
        result = thisChunk.compareTo( thatChunk );
124
      }
125
126
      if( result != 0 ) {
127
        return result;
128
      }
129
    }
130
131
    return s1Length - s2Length;
132
  }
133
}
1134
A src/main/java/com/keenwrite/util/BoundedCache.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.util;
3
4
import java.util.LinkedHashMap;
5
import java.util.Map;
6
7
/**
8
 * A map that removes the oldest entry once its capacity (cache size) has
9
 * been reached.
10
 *
11
 * @param <K> The type of key mapped to a value.
12
 * @param <V> The type of value mapped to a key.
13
 */
14
public final class BoundedCache<K, V> extends LinkedHashMap<K, V> {
15
  private final int mCacheSize;
16
17
  /**
18
   * Constructs a new instance having a finite size.
19
   *
20
   * @param cacheSize The maximum number of entries.
21
   */
22
  public BoundedCache( final int cacheSize ) {
23
    mCacheSize = cacheSize;
24
  }
25
26
  @Override
27
  protected boolean removeEldestEntry( final Map.Entry<K, V> eldest ) {
28
    return size() > mCacheSize;
29
  }
30
}
131
A src/main/java/com/keenwrite/util/CyclicIterator.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.util;
3
4
import java.util.List;
5
import java.util.ListIterator;
6
import java.util.NoSuchElementException;
7
8
/**
9
 * Responsible for iterating over a list either forwards or backwards. When
10
 * the iterator reaches the last element in the list, the next element will
11
 * be the first. When the iterator reaches the first element in the list,
12
 * the previous element will be the last.
13
 * <p>
14
 * Due to the ability to move forwards and backwards through the list, rather
15
 * than force client classes to track the list index independently, this
16
 * iterator provides an accessor to the index. The index is zero-based.
17
 * </p>
18
 *
19
 * @param <T> The type of list to be cycled.
20
 */
21
public final class CyclicIterator<T> implements ListIterator<T> {
22
  private final List<T> mList;
23
24
  /**
25
   * Initialize to an invalid index so that the first calls to either
26
   * {@link #previous()} or {@link #next()} will return the starting or ending
27
   * element.
28
   */
29
  private int mIndex = -1;
30
31
  /**
32
   * Creates an iterator that cycles indefinitely through the given list.
33
   *
34
   * @param list The list to cycle through indefinitely.
35
   */
36
  public CyclicIterator( final List<T> list ) {
37
    mList = list;
38
  }
39
40
  /**
41
   * @return {@code true} if there is at least one element.
42
   */
43
  @Override
44
  public boolean hasNext() {
45
    return !mList.isEmpty();
46
  }
47
48
  /**
49
   * @return {@code true} if there is at least one element.
50
   */
51
  @Override
52
  public boolean hasPrevious() {
53
    return !mList.isEmpty();
54
  }
55
56
  @Override
57
  public int nextIndex() {
58
    return computeIndex( +1 );
59
  }
60
61
  @Override
62
  public int previousIndex() {
63
    return computeIndex( -1 );
64
  }
65
66
  @Override
67
  public void remove() {
68
    mList.remove( mIndex );
69
  }
70
71
  @Override
72
  public void set( final T t ) {
73
    mList.set( mIndex, t );
74
  }
75
76
  @Override
77
  public void add( final T t ) {
78
    mList.add( mIndex, t );
79
  }
80
81
  /**
82
   * Returns the next item in the list, which will cycle to the first
83
   * item as necessary.
84
   *
85
   * @return The next item in the list, cycling to the start if needed.
86
   */
87
  @Override
88
  public T next() {
89
    return cycle( +1 );
90
  }
91
92
  /**
93
   * Returns the previous item in the list, which will cycle to the last
94
   * item as necessary.
95
   *
96
   * @return The previous item in the list, cycling to the end if needed.
97
   */
98
  @Override
99
  public T previous() {
100
    return cycle( -1 );
101
  }
102
103
  /**
104
   * Cycles to the next or previous element, depending on the direction value.
105
   *
106
   * @param direction Use -1 for previous, +1 for next.
107
   * @return The next or previous item in the list.
108
   */
109
  private T cycle( final int direction ) {
110
    try {
111
      return mList.get( mIndex = computeIndex( direction ) );
112
    } catch( final Exception ex ) {
113
      throw new NoSuchElementException( ex );
114
    }
115
  }
116
117
  /**
118
   * Returns the index of the value retrieved from the most recent call to
119
   * either {@link #previous()} or {@link #next()}.
120
   *
121
   * @return The list item index or -1 if no calls have been made to retrieve
122
   * an item from the list.
123
   */
124
  public int getIndex() {
125
    return mIndex;
126
  }
127
128
  private int computeIndex( final int direction ) {
129
    final var i = mIndex + direction;
130
    final var size = mList.size();
131
    final var result = i < 0
132
        ? size - 1
133
        : size == 0 ? 0 : i % size;
134
135
    // Ensure the invariant holds.
136
    assert 0 <= result && result < size || size == 0 && result <= 0;
137
138
    return result;
139
  }
140
}
1141
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
A src/main/java/com/keenwrite/util/FontLoader.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.util;
3
4
import com.keenwrite.preview.HtmlPreview;
5
6
import java.awt.*;
7
import java.awt.font.TextAttribute;
8
import java.io.FileInputStream;
9
import java.io.IOException;
10
import java.io.InputStream;
11
import java.net.URI;
12
import java.util.Map;
13
14
import static com.keenwrite.constants.Constants.FONT_DIRECTORY;
15
import static com.keenwrite.events.StatusEvent.clue;
16
import static com.keenwrite.util.ProtocolScheme.valueFrom;
17
import static com.keenwrite.util.ResourceWalker.walk;
18
import static java.awt.Font.TRUETYPE_FONT;
19
import static java.awt.Font.createFont;
20
import static java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment;
21
import static java.awt.font.TextAttribute.*;
22
23
/**
24
 * Responsible for loading fonts into the application's
25
 * {@link GraphicsEnvironment} so that the {@link HtmlPreview} can display
26
 * the text using a non-system font.
27
 */
28
public final class FontLoader {
29
  /**
30
   * Globbing pattern to match font names.
31
   */
32
  public static final String GLOB_FONTS = "**.{ttf,otf}";
33
34
  /**
35
   * Walks the resources associated with the application to load all TrueType
36
   * font resources found. This method must run before the windowing system
37
   * kicks in, otherwise the fonts will not be found.
38
   * <p>
39
   * All fonts must be TrueType fonts. No PostScript Type 1 fonts are
40
   * supported.
41
   * </p>
42
   */
43
  public static void initFonts() {
44
    // Editor, preview, and TeX fonts
45
    initFonts( FONT_DIRECTORY );
46
47
    // FontAwesome font
48
    initFonts( "/org" );
49
  }
50
51
  @SuppressWarnings( "unchecked" )
52
  private static void initFonts( final String directory ) {
53
    try {
54
      final var ge = getLocalGraphicsEnvironment();
55
      walk(
56
        directory, GLOB_FONTS, path -> {
57
          final var uri = path.toUri();
58
          final var filename = path.toString();
59
60
          try( final var is = openFont( uri, filename ) ) {
61
            final var font = createFont( TRUETYPE_FONT, is );
62
            final var attributes =
63
              (Map<TextAttribute, Integer>) font.getAttributes();
64
65
            attributes.put( LIGATURES, LIGATURES_ON );
66
            attributes.put( KERNING, KERNING_ON );
67
            ge.registerFont( font.deriveFont( attributes ) );
68
          } catch( final Exception ex ) {
69
            clue( ex );
70
          }
71
        }
72
      );
73
    } catch( final Exception ex ) {
74
      clue( ex );
75
    }
76
  }
77
78
  /**
79
   * Attempts to open a font, regardless of whether the font is a resource in
80
   * a JAR file or somewhere on the file system.
81
   *
82
   * @param uri      Directory or archive containing a font.
83
   * @param filename Name of the font file.
84
   * @return An open file handled to the font.
85
   * @throws IOException Could not open the resource as a stream.
86
   */
87
  private static InputStream openFont( final URI uri, final String filename )
88
    throws IOException {
89
    return valueFrom( uri ).isJar()
90
      ? FontLoader.class.getResourceAsStream( filename )
91
      : new FileInputStream( filename );
92
  }
93
}
194
A src/main/java/com/keenwrite/util/GenericBuilder.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.util;
3
4
import java.util.ArrayList;
5
import java.util.List;
6
import java.util.function.BiConsumer;
7
import java.util.function.Consumer;
8
import java.util.function.Function;
9
import java.util.function.Supplier;
10
11
/**
12
 * Responsible for constructing objects that would otherwise require
13
 * a long list of constructor parameters.
14
 * <p>
15
 * See <a href="https://stackoverflow.com/a/31754787/59087">source</a> for
16
 * details.
17
 * </p>
18
 *
19
 * @param <MT> The mutable definition for the type of object to build.
20
 * @param <IT> The immutable definition for the type of object to build.
21
 */
22
public class GenericBuilder<MT, IT> {
23
  /**
24
   * Provides the methods to use for setting object properties.
25
   */
26
  private final Supplier<MT> mMutable;
27
28
  /**
29
   * Calling {@link #build()} will instantiate the immutable instance using
30
   * the mutator.
31
   */
32
  private final Function<MT, IT> mImmutable;
33
34
  /**
35
   * Adds a modifier to call when building an instance.
36
   */
37
  private final List<Consumer<MT>> mModifiers = new ArrayList<>();
38
39
  /**
40
   * Constructs a new builder instance that is capable of populating values for
41
   * any type of object.
42
   *
43
   * @param mutator Provides methods to use for setting object properties.
44
   */
45
  protected GenericBuilder(
46
      final Supplier<MT> mutator, final Function<MT, IT> immutable ) {
47
    assert mutator != null;
48
    assert immutable != null;
49
50
    mMutable = mutator;
51
    mImmutable = immutable;
52
  }
53
54
  /**
55
   * Starting point for building an instance of a particular class.
56
   *
57
   * @param supplier Returns the instance to build.
58
   * @param <MT>     The type of class to build.
59
   * @return A new {@link GenericBuilder} capable of populating data for an
60
   * instance of the class provided by the {@link Supplier}.
61
   */
62
  public static <MT, IT> GenericBuilder<MT, IT> of(
63
      final Supplier<MT> supplier, final Function<MT, IT> immutable ) {
64
    return new GenericBuilder<>( supplier, immutable );
65
  }
66
67
  /**
68
   * Registers a new value with the builder.
69
   *
70
   * @param consumer Accepts a value to be set upon the built object.
71
   * @param value    The value to use when building.
72
   * @param <V>      The type of value used when building.
73
   * @return This {@link GenericBuilder} instance.
74
   */
75
  public <V> GenericBuilder<MT, IT> with(
76
      final BiConsumer<MT, V> consumer, final V value ) {
77
    mModifiers.add( instance -> consumer.accept( instance, value ) );
78
    return this;
79
  }
80
81
  /**
82
   * Instantiates then populates the immutable object to build.
83
   *
84
   * @return The newly built object.
85
   */
86
  public IT build() {
87
    final var value = mMutable.get();
88
    mModifiers.forEach( modifier -> modifier.accept( value ) );
89
    mModifiers.clear();
90
    return mImmutable.apply( value );
91
  }
92
}
193
A src/main/java/com/keenwrite/util/MurmurHash.java
1
package com.keenwrite.util;
2
3
/**
4
 * The MurmurHash3 algorithm was created by Austin Appleby and placed in the
5
 * public domain. This Java port was authored by Yonik Seeley and also placed
6
 * into the public domain. The author hereby disclaims copyright to this
7
 * source code.
8
 * <p>
9
 * This produces exactly the same hash values as the final C++ version and is
10
 * thus suitable for producing the same hash values across platforms.
11
 * <p>
12
 * The 32-bit x86 version of this hash should be the fastest variant for
13
 * relatively short keys like ids. Using {@link #hash32} is a
14
 * good choice for longer strings or returning more than 32 hashed bits.
15
 * <p>
16
 * The x86 and x64 versions do not produce the same results because
17
 * algorithms are optimized for their respective platforms.
18
 * <p>
19
 * Code clean-up by White Magic Software, Ltd.
20
 * </p>
21
 */
22
public final class MurmurHash {
23
  /**
24
   * Returns the 32-bit x86-optimized hash of the UTF-8 bytes of the String
25
   * without actually encoding the string to a temporary buffer. This is over
26
   * twice as fast as hashing the result of {@link String#getBytes()}.
27
   */
28
  @SuppressWarnings( "unused" )
29
  public static int hash32( CharSequence data, int offset, int len, int seed ) {
30
    final int c1 = 0xcc9e2d51;
31
    final int c2 = 0x1b873593;
32
33
    int h1 = seed;
34
35
    int pos = offset;
36
    int end = offset + len;
37
    int k1 = 0;
38
    int k2;
39
    int shift = 0;
40
    int bits;
41
    int nBytes = 0;   // length in UTF8 bytes
42
43
    while( pos < end ) {
44
      int code = data.charAt( pos++ );
45
      if( code < 0x80 ) {
46
        k2 = code;
47
        bits = 8;
48
      }
49
      else if( code < 0x800 ) {
50
        k2 = (0xC0 | (code >> 6))
51
          | ((0x80 | (code & 0x3F)) << 8);
52
        bits = 16;
53
      }
54
      else if( code < 0xD800 || code > 0xDFFF || pos >= end ) {
55
        // we check for pos>=end to encode an unpaired surrogate as 3 bytes.
56
        k2 = (0xE0 | (code >> 12))
57
          | ((0x80 | ((code >> 6) & 0x3F)) << 8)
58
          | ((0x80 | (code & 0x3F)) << 16);
59
        bits = 24;
60
      }
61
      else {
62
        // surrogate pair
63
        // int utf32 = pos < end ? (int) data.charAt(pos++) : 0;
64
        int utf32 = data.charAt( pos++ );
65
        utf32 = ((code - 0xD7C0) << 10) + (utf32 & 0x3FF);
66
        k2 = (0xff & (0xF0 | (utf32 >> 18)))
67
          | ((0x80 | ((utf32 >> 12) & 0x3F))) << 8
68
          | ((0x80 | ((utf32 >> 6) & 0x3F))) << 16
69
          | (0x80 | (utf32 & 0x3F)) << 24;
70
        bits = 32;
71
      }
72
73
      k1 |= k2 << shift;
74
75
      // int used_bits = 32 - shift;  // how many bits of k2 were used in k1.
76
      // int unused_bits = bits - used_bits; //  (bits-(32-shift)) ==
77
      // bits+shift-32  == bits-newshift
78
79
      shift += bits;
80
      if( shift >= 32 ) {
81
        // mix after we have a complete word
82
83
        k1 *= c1;
84
        k1 = (k1 << 15) | (k1 >>> 17);  // ROTL32(k1,15);
85
        k1 *= c2;
86
87
        h1 ^= k1;
88
        h1 = (h1 << 13) | (h1 >>> 19);  // ROTL32(h1,13);
89
        h1 = h1 * 5 + 0xe6546b64;
90
91
        shift -= 32;
92
        // unfortunately, java won't let you shift 32 bits off, so we need to
93
        // check for 0
94
        if( shift != 0 ) {
95
          k1 = k2 >>> (bits - shift);   // bits used == bits - newshift
96
        }
97
        else {
98
          k1 = 0;
99
        }
100
        nBytes += 4;
101
      }
102
103
    } // inner
104
105
    // handle tail
106
    if( shift > 0 ) {
107
      nBytes += shift >> 3;
108
      k1 *= c1;
109
      k1 = (k1 << 15) | (k1 >>> 17);  // ROTL32(k1,15);
110
      k1 *= c2;
111
      h1 ^= k1;
112
    }
113
114
    // finalization
115
    h1 ^= nBytes;
116
117
    // fmix(h1);
118
    h1 ^= h1 >>> 16;
119
    h1 *= 0x85ebca6b;
120
    h1 ^= h1 >>> 13;
121
    h1 *= 0xc2b2ae35;
122
    h1 ^= h1 >>> 16;
123
124
    return h1;
125
  }
126
}
1127
A src/main/java/com/keenwrite/util/ProtocolScheme.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.util;
3
4
import java.io.File;
5
import java.net.MalformedURLException;
6
import java.net.URI;
7
import java.net.URL;
8
9
import static com.keenwrite.events.StatusEvent.clue;
110
11
/**
12
 * Represents the type of durigetProtocol( new URI( uriuri.startsWith( "//" ) ? HTTP : valueFrom( new File( uri ) );
13
    }
14
  }uriURI uri )
15
    throws MalformedURLException {
16
: valueFrom( uri.toURL
A src/main/java/com/keenwrite/util/ResourceWalker.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.util;
13
4
import java.io.IOException;
5
import java.net.URISyntaxException;
6
import java.nio.file.FileSystem;
7
import java.nio.file.Pat, regardless if they exist within
8
 * a Java Archive (.jar) file or on the native file system.
9
 *
10
 * @see FileWalker#walk(Path, String, Consumer)Walks the given directory hierarchy for files that match the given
11
   * globbing file name pattern.
12
   glob      Only files matching the pattern will be consumed {
13
        FileWalker.walk( path, glob, c );
A src/main/r/README.md
1
# R Scripts
12
3
These R scripts illustrate how R can be used within an application to perform calculations using variables. Authors are free to write their own scripts, of course. These scripts serve as an example of how to automate certain tasks while writicalculate a total for all numeric columns
A src/main/r/conversion.R
1
# ########################################################################
2
#
3
# Substitute R expressions in a document with their evaluated value. The
4
# anchor variable must be set for functions that use relative dates.
5
#
6
# ########################################################################
7
8
# Evaluates an expression; writes s if there is no expression.
9
x <- function( s ) {
10
  return(
11
    tryCatch({
12
      r = eval( parse( text=s ) )
13
14
      # If the result isn't primitive, then it was probably parsed into
15
      # an unprintable object (e.g., "gray" becomes a colour). In those
16
      # cases, return the original text string. Otherwise, an atomic
17
      # value means a primitive type (string, integer, etc.) that can be
18
      # written directly into the document.
19
      #
20
      # See: http://stackoverflow.com/a/19501276/59087
21
      if( is.atomic( r ) ) {
22
        r
23
      }
24
      else {
25
        s
26
      }
27
    },
28
    warning = function( w ) {
29
      s
30
    },
31
    error = function( e ) {
32
      s
33
    })
34
  )
35
}
36
37
# Returns a date offset by a given number of days, relative to the given
38
# date (d). This does not use the anchor, but is used to get the anchor's
39
# value as a date.
40
when <- function( d, n = 0, format = "%Y-%m-%d" ) {
41
  as.Date( d, format = format ) + x( n )
42
}
43
44
# Full date (s) offset by an optional number of days before or after.
45
# This will remove leading zeros (applying leading spaces instead, which
46
# are ignored by any worthwhile typesetting engine).
47
annal <- function( days = 0, format = "%Y-%m-%d", oformat = "%B %d, %Y" ) {
48
  format( when( anchor, days ), format = oformat )
49
}
50
51
# Extracts the year from a date string.
52
year <- function( days = 0, format = "%Y-%m-%d" ) {
53
  annal( days, format, "%Y" )
54
}
55
56
# Day of the week (in days since the anchor date).
57
weekday <- function( n ) {
58
  weekdays( when( anchor, n ) )
59
}
60
61
# String concatenate function alias because paste0 is a terrible name.
62
concat <- paste0
63
64
# Translates a number from digits to words using Chicago Manual of Style.
65
# This does not translate numbers greater than one hundred. If ordinal
66
# is TRUE, this will return the ordinal name. This will not produce ordinals
67
# for numbers greater than 100
68
cms <- function( n, ordinal = FALSE ) {
69
  n <- x( n )
70
71
  # We're done here.
72
  if( n == 0 ) {
73
    if( ordinal ) {
74
      return( "zeroth" )
75
    }
76
77
    return( "zero" )
78
  }
79
80
  # Concatenate this a little later.
81
  if( n < 0 ) {
82
    result = "negative "
83
    n = abs( n )
84
  }
85
86
  # Do not spell out numbers greater than one hundred.
87
  if( n > 100 ) {
88
    # Comma-separated numbers.
89
    return( format( n, big.mark=",", trim=TRUE, scientific=FALSE ) )
90
  }
91
92
  # Don't go beyond 100.
93
  if( n == 100 ) {
94
    if( ordinal ) {
95
      return( "one hundredth" )
96
    }
97
98
    return( "one hundred" )
99
  }
100
101
  # Samuel Langhorne Clemens noted English has too many exceptions.
102
  small = c(
103
    "one", "two", "three", "four", "five",
104
    "six", "seven", "eight", "nine", "ten",
105
    "eleven", "twelve", "thirteen", "fourteen", "fifteen",
106
    "sixteen", "seventeen", "eighteen", "nineteen"
107
  )
108
109
  ord_small = c(
110
    "first", "second", "third", "fourth", "fifth",
111
    "sixth", "seventh", "eighth", "ninth", "tenth",
112
    "eleventh", "twelfth", "thirteenth", "fourteenth", "fifteenth",
113
    "sixteenth", "seventeenth", "eighteenth", "nineteenth", "twentieth"
114
  )
115
116
  # After this, the number (n) is between 20 and 99.
117
  if( n < 20 ) {
118
    if( ordinal ) {
119
      return( .subset( ord_small, n %% 100 ) )
120
    }
121
122
    return( .subset( small, n %% 100 ) )
123
  }
124
125
  tens = c( "",
126
    "twenty", "thirty", "forty", "fifty",
127
    "sixty", "seventy", "eighty", "ninety"
128
  )
129
130
  ord_tens = c( "",
131
    "twentieth", "thirtieth", "fortieth", "fiftieth",
132
    "sixtieth", "seventieth", "eightieth", "ninetieth"
133
  )
134
135
  ones_index = n %% 10
136
  n = n %/% 10
137
138
  # No number in the ones column, so the number must be a multiple of ten.
139
  if( ones_index == 0 ) {
140
    if( ordinal ) {
141
      return( .subset( ord_tens, n ) )
142
    }
143
144
    return( .subset( tens, n ) )
145
  }
146
147
  # Find the value from the ones column.
148
  if( ordinal ) {
149
    unit_1 = .subset( ord_small, ones_index )
150
  }
151
  else {
152
    unit_1 = .subset( small, ones_index )
153
  }
154
155
  # Find the tens column.
156
  unit_10 = .subset( tens, n )
157
158
  # Hyphenate the tens and the ones together.
159
  concat( unit_10, concat( "-", unit_1 ) )
160
}
161
162
# Returns a human-readable string that provides the elapsed time between
163
# two numbers in terms of years, months, and days. If any unit value is zero,
164
# the unit is not included. The words (year, month, day) are pluralized
165
# according to English grammar. The numbers are written out according to
166
# Chicago Manual of Style. This applies the serial comma.
167
#
168
# Both numbers are offsets relative to the anchor date.
169
#
170
# If all unit values are zero, this returns s ("same day" by default).
171
#
172
# If the start date (began) is greater than end date (ended), the dates are
173
# swapped before calculations are performed. This allows any two dates
174
# to be compared and positive unit values are always returned.
175
#
176
elapsed <- function( began, ended, s = "same day" ) {
177
  began = when( anchor, began )
178
  ended = when( anchor, ended )
179
180
  # Swap the dates if the end date comes before the start date.
181
  if( as.integer( ended - began ) < 0 ) {
182
    tempd = began
183
    began = ended
184
    ended = tempd
185
  }
186
187
  # Calculate number of elapsed years.
188
  years = length( seq( from = began, to = ended, by = 'year' ) ) - 1
189
190
  # Move the start date up by the number of elapsed years.
191
  if( years > 0 ) {
192
    began = seq( began, length = 2, by = concat( years, " years" ) )[2]
193
    years = pl.numeric( "year", years )
194
  }
195
  else {
196
    # Zero years.
197
    years = ""
198
  }
199
200
  # Calculate number of elapsed months, excluding years.
201
  months = length( seq( from = began, to = ended, by = 'month' ) ) - 1
202
203
  # Move the start date up by the number of elapsed months
204
  if( months > 0 ) {
205
    began = seq( began, length = 2, by = concat( months, " months" ) )[2]
206
    months = pl.numeric( "month", months )
207
  }
208
  else {
209
    # Zero months
210
    months = ""
211
  }
212
213
  # Calculate number of elapsed days, excluding months and years.
214
  days = length( seq( from = began, to = ended, by = 'day' ) ) - 1
215
216
  if( days > 0 ) {
217
    days = pl.numeric( "day", days )
218
  }
219
  else {
220
    # Zero days
221
    days = ""
222
  }
223
224
  if( years <= 0 && months <= 0 && days <= 0 ) {
225
    return( s )
226
  }
227
228
  # Put them all in a vector, then remove the empty values.
229
  s <- c( years, months, days )
230
  s <- s[ s != "" ]
231
232
  r <- paste( s, collapse = ", " )
233
234
  # If all three items are present, replace the last comma with ", and".
235
  if( length( s ) > 2 ) {
236
    return( gsub( "(.*),", "\\1, and", r ) )
237
  }
238
239
  # Does nothing if no commas are present.
240
  gsub( "(.*),", "\\1 and", r )
241
}
242
243
# Returns the number (n) in English followed by the plural or singular
244
# form of the given string (s; resumably a noun), if applicable, according
245
# to English grammar. That is, pl.numeric( "wolf", 5 ) will return
246
# "five wolves".
247
pl.numeric <- function( s, n ) {
248
  concat( cms( n ), concat( " ", pluralize( s, n ) ) )
249
}
250
251
# Name of the season, starting with an capital letter.
252
season <- function( n, format = "%Y-%m-%d" ) {
253
  WS <- as.Date("2016-12-15", "%Y-%m-%d") # Winter Solstice
254
  SE <- as.Date("2016-03-15", "%Y-%m-%d") # Spring Equinox
255
  SS <- as.Date("2016-06-15", "%Y-%m-%d") # Summer Solstice
256
  AE <- as.Date("2016-09-15", "%Y-%m-%d") # Autumn Equinox
257
258
  d <- when( anchor, n )
259
  d <- as.Date( strftime( d, format="2016-%m-%d" ) )
260
261
  ifelse( d >= WS | d < SE, "Winter",
262
    ifelse( d >= SE & d < SS, "Spring",
263
      ifelse( d >= SS & d < AE, "Summer", "Autumn" )
264
    )
265
  )
266
}
267
268
# Converts the first letter in a string to lowercase
269
lc <- function( s ) {
270
  concat( tolower( substr( s, 1, 1 ) ), substr( s, 2, nchar( s ) ) )
271
}
272
273
# Converts the first letter in a string to uppercase
274
uc <- function( s ) {
275
  concat( toupper( substr( s, 1, 1 ) ), substr( s, 2, nchar( s ) ) )
276
}
277
278
# Returns the number of days between the given dates.
279
days <- function( d1, d2, format = "%Y-%m-%d" ) {
280
  dates = c( d1, d2 )
281
  dt = strptime( dates, format = format )
282
  as.integer( difftime( dates[2], dates[1], units = "days" ) )
283
}
284
285
# Returns the number of years elapsed.
286
years <- function( began, ended ) {
287
  began = when( anchor, began )
288
  ended = when( anchor, ended )
289
290
  # Swap the dates if the end date comes before the start date.
291
  if( as.integer( ended - began ) < 0 ) {
292
    tempd = began
293
    began = ended
294
    ended = tempd
295
  }
296
297
  # Calculate number of elapsed years.
298
  length( seq( from = began, to = ended, by = 'year' ) ) - 1
299
}
300
301
# Full name of the month, starting with a capital letter.
302
month <- function( n ) {
303
  # Faster than month.name[ x( n ) ]
304
  .subset( month.name, x( n ) )
305
}
306
307
money <- function( n ) {
308
  formatC( x( n ), format="d" )
309
}
1310
A src/main/r/csv.R
1
# ######################################################################
2
#
3
# Copyright 2016, White Magic Software, Ltd.
4
# 
5
# Permission is hereby granted, free of charge, to any person obtaining
6
# a copy of this software and associated documentation files (the
7
# "Software"), to deal in the Software without restriction, including
8
# without limitation the rights to use, copy, modify, merge, publish,
9
# distribute, sublicense, and/or sell copies of the Software, and to
10
# permit persons to whom the Software is furnished to do so, subject to
11
# the following conditions:
12
# 
13
# The above copyright notice and this permission notice shall be
14
# included in all copies or substantial portions of the Software.
15
# 
16
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
#
24
# ######################################################################
25
26
# ######################################################################
27
#
28
# Converts CSV to Markdown.
29
#
30
# ######################################################################
31
32
# Reads a CSV file and converts the contents to a Markdown table. The
33
# file must be in the working directory as specified by setwd.
34
#
35
# @param f The filename to convert.
36
# @param decimals Rounded decimal places (default 1).
37
# @param totals Include total sums (default TRUE).
38
# @param align Right-align numbers (default TRUE).
39
csv2md <- function( f, decimals = 1, totals = T, align = T ) {
40
  # Read the CVS data from the file; ensure strings become characters.
41
  df <- read.table( f, sep=',', header=T, stringsAsFactors=F )
42
43
  if( totals ) {
44
    # Determine what columns can be summed.
45
    number <- which( unlist( lapply( df, is.numeric ) ) )
46
47
    # Use colSums when more than one summable column exists.
48
    if( length( number ) > 1 ) {
49
      f.sum <- colSums
50
    }
51
    else {
52
      f.sum <- sum
53
    }
54
55
    # Calculate the sum of all the summable columns and insert the
56
    # results back into the data frame.
57
    df[ (nrow( df ) + 1), number ] <- f.sum( df[, number], na.rm=TRUE )
58
59
    # pluralize would be heavyweight here.
60
    if( length( number ) > 1 ) {
61
      t <- "**Totals**"
62
    }
63
    else {
64
      t <- "**Total**"
65
    }
66
67
    # Change the first column of the last line to "Total(s)".
68
    df[ nrow( df ), 1 ] <- t
69
70
    # Don't clutter the output with "NA" text.
71
    df[ is.na( df ) ] <- ""
72
  }
73
74
  if( align ) {
75
    is.char <- vapply( df, is.character, logical( 1 ) )
76
    dashes <- paste( ifelse( is.char, ':---', '---:' ), collapse='|' )
77
  }
78
  else {
79
    dashes <- paste( rep( '---', length( df ) ), collapse = '|')
80
  }
81
82
  # Create a Markdown version of the data frame.
83
  paste(
84
    paste( names( df ), collapse = '|'), '\n',
85
    dashes, '\n', 
86
    paste(
87
      Reduce( function( x, y ) {
88
          paste( x, format( y, digits = decimals ), sep = '|' )
89
        }, df
90
      ),
91
      collapse = '|\n', sep=''
92
    )
93
  )
94
}
95
196
A src/main/r/pluralize.R
1
# ######################################################################
2
#
3
# Copyright 2016, White Magic Software, Ltd.
4
# 
5
# Permission is hereby granted, free of charge, to any person obtaining
6
# a copy of this software and associated documentation files (the
7
# "Software"), to deal in the Software without restriction, including
8
# without limitation the rights to use, copy, modify, merge, publish,
9
# distribute, sublicense, and/or sell copies of the Software, and to
10
# permit persons to whom the Software is furnished to do so, subject to
11
# the following conditions:
12
# 
13
# The above copyright notice and this permission notice shall be
14
# included in all copies or substantial portions of the Software.
15
# 
16
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
#
24
# ######################################################################
25
26
# ######################################################################
27
#
28
# See Damian Conway's "An Algorithmic Approach to English Pluralization":
29
#   http://goo.gl/oRL4MP
30
# See Oliver Glerke's Evo Inflector: https://github.com/atteo/evo-inflector/
31
# See Shevek's Pluralizer: https://github.com/shevek/linguistics/
32
# See also: http://www.freevectors.net/assets/files/plural.txt
33
#
34
# ######################################################################
35
36
pluralize <- function( s, n ) {
37
  result <- s
38
39
  # Partial implementation of Conway's algorithm for nouns.
40
  if( n != 1 ) {
41
    if( pl.noninflective( s ) ||
42
        pl.suffix( "fish", s ) ||
43
        pl.suffix( "ois", s ) ||
44
        pl.suffix( "sheep", s ) ||
45
        pl.suffix( "deer", s ) ||
46
        pl.suffix( "pox", s ) ||
47
        pl.suffix( "[A-Z].*ese", s ) ||
48
        pl.suffix( "itis", s ) ) {
49
      # 1. Retain non-inflective user-mapped noun as is.
50
      # 2. Retain non-inflective plural as is.
51
      result <- s
52
    }
53
    else if( pl.is.irregular.pl( s ) ) {
54
      # 4. Change irregular plurals based on mapping.
55
      result <- pl.irregular.pl( s )
56
    }
57
    else if( pl.is.irregular.es( s ) ) {
58
      # x. From Shevek's Pluralizer
59
      result <- pl.inflect( s, "", "es" )
60
    }
61
    else if( pl.suffix( "man", s ) ) {
62
      # 5. For -man, change -an to -en
63
      result <- pl.inflect( s, "an", "en" )
64
    }
65
    else if( pl.suffix( "[lm]ouse", s ) ) {
66
      # 5. For [lm]ouse, change -ouse to -ice
67
      result <- pl.inflect( s, "ouse", "ice" )
68
    }
69
    else if( pl.suffix( "tooth", s ) ) {
70
      # 5. For -tooth, change -ooth to -eeth
71
      result <- pl.inflect( s, "ooth", "eeth" )
72
    }
73
    else if( pl.suffix( "goose", s ) ) {
74
      # 5. For -goose, change -oose to -eese
75
      result <- pl.inflect( s, "oose", "eese" )
76
    }
77
    else if( pl.suffix( "foot", s ) ) {
78
      # 5. For -foot, change -oot to -eet
79
      result <- pl.inflect( s, "oot", "eet" )
80
    }
81
    else if( pl.suffix( "zoon", s ) ) {
82
      # 5. For -zoon, change -on to -a
83
      result <- pl.inflect( s, "on", "a" )
84
    }
85
    else if( pl.suffix( "[csx]is", s ) ) {
86
      # 5. Change -cis, -sis, -xis to -es
87
      result <- pl.inflect( s, "is", "es" )
88
    }
89
    else if( pl.suffix( "([cs]h|ss)", s ) ) {
90
      # 8. Change -ch, -sh, -ss to -es
91
      result <- pl.inflect( s, "", "es" )
92
    }
93
    else if( pl.suffix( "([aeo]lf|[^d]eaf|arf)", s ) ) {
94
      # 9. Change -f to -ves
95
      result <- pl.inflect( s, "f", "ves" )
96
    }
97
    else if( pl.suffix( "[nlw]ife", s ) ) {
98
      # 9. Change -fe to -ves
99
      result <- pl.inflect( s, "fe", "ves" )
100
    }
101
    else if( pl.suffix( "([aeiou]y|[A-Z].*y)", s ) ) {
102
      # 10. Change -y to -ys.
103
      result <- pl.inflect( s, "", "s" )
104
    }
105
    else if( pl.suffix( "y", s ) ) {
106
      # 10. Change -y to -ies.
107
      result <- pl.inflect( s, "y", "ies" )
108
    }
109
    else {
110
      # 13. Default plural: add -s.
111
      result <- pl.inflect( s, "", "s" )
112
    }
113
  }
114
115
  result
116
}
117
118
# Pluralize s if n is not equal to 1.
119
pl <- function( s, n ) {
120
  pluralize( s, x( n ) )
121
}
122
123
# Returns the given string (s) with its suffix replaced by r.
124
pl.inflect <- function( s, suffix, r ) {
125
  gsub( paste( suffix, "$", sep="" ), r, s )
126
}
127
128
# Answers whether the given string (s) has the given ending.
129
pl.suffix <- function( ending, s ) {
130
  grepl( paste( ending, "$", sep="" ), s )
131
}
132
133
# Answers whether the given string (s) is a noninflective noun.
134
pl.noninflective <- function( s ) {
135
  v <- c(
136
    "aircraft", "Bhutanese", "bison", "bream", "breeches", "britches",
137
    "Burmese", "carp", "chassis", "Chinese", "clippers", "cod", "contretemps",
138
    "corps", "debris", "diabetes", "djinn", "eland", "elk", "flounder",
139
    "fracas", "gallows", "graffiti", "headquarters", "herpes", "high-jinks",
140
    "homework", "hovercraft", "innings", "jackanapes", "Japanese",
141
    "Lebanese", "mackerel", "means", "measles", "mews", "mumps", "news",
142
    "pincers", "pliers", "Portuguese", "proceedings", "rabies", "salmon",
143
    "scissors", "sea-bass", "Senegalese", "series", "shears", "Siamese",
144
    "Sinhalese", "spacecraft", "species", "swine", "trout", "tuna",
145
    "Vietnamese", "watercraft", "whiting", "wildebeest"
146
  )
147
148
  is.element( s, v )
149
}
150
151
# Answers whether the given string (s) is an irregular plural.
152
pl.is.irregular.pl <- function( s ) {
153
  # Could be refactored with pl.irregular.pl...
154
  v <- c(
155
    "beef", "brother", "child", "cow", "ephemeris", "genie", "money",
156
    "mongoose", "mythos", "octopus", "ox", "soliloquy", "trilby"
157
  )
158
159
  is.element( s, v )
160
}
161
162
# Call to pluralize an irregular noun. Only call after confirming
163
# the noun is irregular via pl.is.irregular.pl.
164
pl.irregular.pl <- function( s ) {
165
  v <- list(
166
    "beef" = "beefs",
167
    "brother" = "brothers",
168
    "child" = "children",
169
    "cow" = "cows",
170
    "ephemeris" = "ephemerides",
171
    "genie" = "genies",
172
    "money" = "moneys",
173
    "mongoose" = "mongooses",
174
    "mythos" = "mythoi",
175
    "octopus" = "octopuses",
176
    "ox" = "oxen",
177
    "soliloquy" = "soliloquies",
178
    "trilby" = "trilbys"
179
  )
180
181
  # Faster version of v[[ s ]]
182
  .subset2( v, s )
183
}
184
185
# Answers whether the given string (s) pluralizes with -es.
186
pl.is.irregular.es <- function( s ) {
187
  v <- c(
188
    "acropolis", "aegis", "alias", "asbestos", "bathos", "bias", "bronchitis",
189
    "bursitis", "caddis", "cannabis", "canvas", "chaos", "cosmos", "dais",
190
    "digitalis", "epidermis", "ethos", "eyas", "gas", "glottis", "hubris",
191
    "ibis", "lens", "mantis", "marquis", "metropolis", "pathos", "pelvis",
192
    "polis", "rhinoceros", "sassafrass", "trellis"
193
  )
194
195
  is.element( s, v )
196
}
197
1198
A src/main/resources/META-INF/services/com.keenwrite.service.Settings
1
1
com.keenwrite.service.impl.DefaultSettings
A src/main/resources/META-INF/services/com.keenwrite.service.events.Notifier
1
1
com.keenwrite.service.events.impl.DefaultNotifier
A src/main/resources/bootstrap.properties
1
# Used by the Gradle build script and the application.
2
application.title=KeenWrite
3
14
A src/main/resources/com/keenwrite/.gitignore
1
app.properties
12
A src/main/resources/com/keenwrite/app-title.svg
1
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
  971.53119"
8
   height="498.39355"
9
   viewBox="0 0 971.53119 498.3935app-title
10
   inkscape:export-filename="/home/jarvisd/dev/java/scrivenvar/docs/images/app-title.png"
11
   inkscape:export-xdpi="24.66"
12
   inkscape:export-ydpi="24.66 /455.5775"
13
   inkscape:cy="347.59625
14
   fit-margin-top="0"
15
   fit-margin-left="0"
16
   fit-margin-right="0"
17
   fit-margin-bottom="033
18
   transform="translate(-394.35834,-171.20491)"opacity:1opacity:1opacity:1fill:#000000transform="translate(-394.35834,-171.20491)" />"
19
   x="311.66693"
20
   y="402.2062766693"
21
     y="402.20627
A src/main/resources/com/keenwrite/build.sh
1
#!/bin/bash
2
3
INKSCAPE="/usr/bin/inkscape"
4
PNG_COMPRESS="optipng"
5
PNG_COMPRESS_OPTS="-o9 *png"
6
ICO_TOOL="icotool"
7
ICO_TOOL_OPTS="-c -o ../../../../../icons/logo.ico logo64.png"
8
9
declare -a SIZES=("16" "32" "64" "128" "256" "512")
110
11
for i in "${SIZES[@]}"; dw "${i}" --export-overwrite --export-type=png -o "logo${i}.png" "logo.svg" 
A src/main/resources/com/keenwrite/editor/markdown.css
1
/* Copyright 2020 White Magic Software, Ltd. -- All rights reserved. */
2
3
.markdown {
4
  -fx-font-family: 'Noto Sans';
5
  -fx-font-size: 11pt;
6
  -fx-padding: .25em;
7
}
8
9
/* Editor background color */
10
.styled-text-area {
11
  -fx-background-color: -fx-control-inner-background;
12
}
13
14
/* Text foreground colour */
15
.styled-text-area .text {
16
  -fx-fill: -fx-text-foreground;
17
}
118
19
/* Subtly highlight the current paragraph. */
20
.markdown .paragraph-box:has-caret {
21
  -fx-b-fx-text-background-fx-text-selection 255, 131, 67, .7 
A src/main/resources/com/keenwrite/editor/markdown_en-Latn-AU.css
11
A src/main/resources/com/keenwrite/editor/markdown_en-Latn-CA.css
11
A src/main/resources/com/keenwrite/editor/markdown_en-Latn-GB.css
11
A src/main/resources/com/keenwrite/editor/markdown_en-Latn-NZ.css
11
A src/main/resources/com/keenwrite/editor/markdown_en-Latn-US.css
11
A src/main/resources/com/keenwrite/editor/markdown_en-Latn-ZA.css
11
A src/main/resources/com/keenwrite/editor/markdown_ja-Jpan-JP.css
1
.markdown {
2
  -fx-font-family: 'Noto Sans CJK JP';
3
}
14
A src/main/resources/com/keenwrite/editor/markdown_ko-Kore-KR.css
1
.markdown {
2
  -fx-font-family: 'Noto Sans CJK KR';
3
}
14
A src/main/resources/com/keenwrite/editor/markdown_zh-Hans-CN.css
1
.markdown {
2
  -fx-font-family: 'Noto Sans CJK SC';
3
}
14
A src/main/resources/com/keenwrite/editor/markdown_zh-Hans-SG.css
1
.markdown {
2
  -fx-font-family: 'Noto Sans CJK SC';
3
}
14
A src/main/resources/com/keenwrite/editor/markdown_zh-Hant-HK.css
1
.markdown {
2
  -fx-font-family: 'Noto Sans CJK HK';
3
}
14
A src/main/resources/com/keenwrite/editor/markdown_zh-Hant-TW.css
1
.markdown {
2
  -fx-font-family: 'Noto Sans CJK TC';
3
}
14
A src/main/resources/com/keenwrite/logo.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
  
8
   sodipodi:docname="icon.svg"
9
   id="svg52"
10
   xml:space="preserve"
11
   viewBox="0 0 512 512"
12
   height="512"
13
   width="512"
14
   version="1.1
15
   inkscape:cy="369.17559"
16
   inkscape:cx="343.24925objecttolerance="10bordercolor="#666666id="rect933"
17
   height="175.55823"
18
   width="470.12033"
19
   y="132.06313"
20
   x="114.92139x1="0.15235768"
21
   y1="-0.0449115712="-0.049471263">
22
<stop
23
   offset="0%id="stop9" />
24
<stop
25
   offset="100%id="stop11transform="translate(-384.01706,-164.40168)"id="path14 /><path
26
     id="path22opacity:1" /><path
27
     id="path26opacity:1" /><path
28
     id="path30" /><path
29
     id="path34" /><path
30
     id="path38" /><path
31
     id="path42opacity:1" /></g>
32
33
<text
34
   style="fill:#000000id="text931"
35
   xml:space="preserve" /></svg>
136
A src/main/resources/com/keenwrite/logo128.png
Binary file
A src/main/resources/com/keenwrite/logo16.png
Binary file
A src/main/resources/com/keenwrite/logo256.png
Binary file
A src/main/resources/com/keenwrite/logo32.png
Binary file
A src/main/resources/com/keenwrite/logo512.png
Binary file
A src/main/resources/com/keenwrite/logo64.png
Binary file
A src/main/resources/com/keenwrite/messages.properties
1
# ########################################################################
2
# Main Application Window
3
# ########################################################################
4
5
# suppress inspection "UnusedProperty" for whole file
16
7
# #####################
A src/main/resources/com/keenwrite/preview/webview.css
1
body,h1,h2,h3,h4,h5,h6,ol,p,ul{margin:0;padding:0}img{max-width:100%;height:auto}table{table-collapse:collapse;table-spacing:0;border-spacing:0}
12
3
/* Do not use points (pt): FlyingSaucer on Debian fails to render. */
4
body
A src/main/resources/com/keenwrite/preview/webview_ja-Jpan-JP.css
1
body {
2
  font-family: 'Noto Serif CJK JP';
3
}
4
5
pre, code, tt {
6
  font-family: 'Noto Sans Mono CJK JP';
7
}
18
A src/main/resources/com/keenwrite/preview/webview_ko-Kore-KR.css
1
body {
2
  font-family: 'Noto Serif CJK KR';
3
}
4
5
pre, code, tt {
6
  font-family: 'Noto Sans Mono CJK KR';
7
}
18
A src/main/resources/com/keenwrite/preview/webview_zh-Hans-CN.css
1
body {
2
  font-family: 'Noto Serif CJK SC';
3
}
4
5
pre, code, tt {
6
  font-family: 'Noto Sans Mono CJK SC';
7
}
18
A src/main/resources/com/keenwrite/preview/webview_zh-Hans-SG.css
1
body {
2
  font-family: 'Noto Serif CJK SC';
3
}
4
5
pre, code, tt {
6
  font-family: 'Noto Sans Mono CJK SC';
7
}
18
A src/main/resources/com/keenwrite/preview/webview_zh-Hant-HK.css
1
body {
2
  font-family: 'Noto Serif CJK SC';
3
}
4
5
pre, code, tt {
6
  font-family: 'Noto Sans Mono CJK HK';
7
}
18
A src/main/resources/com/keenwrite/preview/webview_zh-Hant-TW.css
1
body {
2
  font-family: 'Noto Serif CJK TC';
3
}
4
5
pre, code, tt {
6
  font-family: 'Noto Sans Mono CJK TC';
7
}
18
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 , all other contractions can be hard-coded into either regular expressions or EBNF grammars.
6
17
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
A src/main/resources/com/keenwrite/settings.properties
1
# ########################################################################
2
# Application
3
# ########################################################################
14
5
application.title=keenwrite
6
applica=untitled.md
A src/main/resources/com/keenwrite/skins/count_darcula.css
1
.root {
2
  -fx-base: rgb( 43, 43, 43 );
3
  -fx-background: -fx-base;: -fx-base;
4
187, 187, 187 );
5
  -fx-mid-text-color: derive( -fx-base, 100%derive( -fx-base, 25% );
6
  -fx-text-foreground: -fx-light-text-color;
7
  -fx-text-background7.5% );
8
  -fx-text-selection45% );
9
10
  /* Make controls ( buttons, thumb, etc. ) slightly lighter */
11
  -fx-color: derive( -fx-base20% );
12
}
113
14
.caret {
15
  -fx-stroke: -fx-accentfx-light-text-color;
16
  -fx-fill:hover {
17
  -fx-effect: dropshadow( three-pass-box, rgba( 0, 0, 0, 0.2 ), 4, 0, 0, 0 ) -fx-light-text-color
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;
16
7
  /* Make controls ( buttons, thumb, etc. ) slightly lighter */
8
  -fx-color: derive( -fx-base      
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
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 R          
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;
17
8
 : derive( -fx-base, 150% );
9
  -fx-mid-text-color: derive( -fx-        
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-40% );
110
11
  -fx-control-inner-background: -fx-base;
12
 , 5
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% );
19
10
  /* Control background */
11
      /* Text colors */
12
             /* Accent colors */
13
  -fx-accent: rgb( 51, 51, 52 );
14
              -item {
15
      -fx-border-insets: -1;
16
    {
17
  -fx-min-width: 80px;
18
    -fx-border-insets: -1;
19
        -fx-opacity: 1.0;
20
              -fx-padding: 2 2 1 2;
21
  -fx-border-insets: 0;
22
  1 1;
23
      -fx-padding: 2;
24
  -fx-border-insets: 0;
25
          6, 56, 59 );
26
        -fx-padding: -1;
27
        -fx-padding: -1;
28
  -fx-border-insets: 0;
29
  1 0 1;
30
      -fx-padding: 2;
31
        -fx-padding: 0;
32
      1 0 0;
33
                      hyperlink {
34
                                          
A src/main/resources/com/keenwrite/ui/fonts/icons/3g2.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/3ga.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/3gp.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/7z.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/aa.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/aac.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ac.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/accdb.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/accdt.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ace.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/adn.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ai.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/aif.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/aifc.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/aiff.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ait.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/amr.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ani.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/apk.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/app.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/applescript.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/asax.svg
1
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.852d5006e"/></svg>
A src/main/resources/com/keenwrite/ui/fonts/icons/asc.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ascx.svg
1
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.852d5006e"/></svg>
A src/main/resources/com/keenwrite/ui/fonts/icons/asf.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ash.svg
1
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/main/resources/com/keenwrite/ui/fonts/icons/ashx.svg
1
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.852d5006e"/></svg>
A src/main/resources/com/keenwrite/ui/fonts/icons/asm.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/asmx.svg
1
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.852d5006e"/></svg>
A src/main/resources/com/keenwrite/ui/fonts/icons/asp.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/aspx.svg
1
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.852d5006e"/></svg>
A src/main/resources/com/keenwrite/ui/fonts/icons/asx.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/au.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/aup.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/avi.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/axd.svg
1
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.852d5006e"/></svg>
A src/main/resources/com/keenwrite/ui/fonts/icons/aze.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/bak.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/bash.svg
1
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/main/resources/com/keenwrite/ui/fonts/icons/bat.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/bin.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/blank.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/bmp.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/bowerrc.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/bpg.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/bz2.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/bzempty.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/c.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/cab.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/cad.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/caf.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/cal.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/cdda.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/cer.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/cfg.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/cfm.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/cfml.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/cgi.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/chm.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/class.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/cmd.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/coffee.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/coffeelintignore.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/com.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/compile.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/conf.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/config.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/cpp.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/cptx.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/cr2.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/crt.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/crypt.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/cs.svg
1
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.852d5006e"/></svg>
A src/main/resources/com/keenwrite/ui/fonts/icons/csh.svg
1
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/main/resources/com/keenwrite/ui/fonts/icons/cson.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/css.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/csv.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/cue.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/cur.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/dart.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/dat.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/data.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/db.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/dbf.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/deb.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/dgn.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/dist.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/diz.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/dll.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/dmg.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/dng.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/doc.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/docb.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/docm.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/docx.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/dot.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/dotm.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/dotx.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/download.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/dpj.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ds_store.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/dsn.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/dtd.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/dwg.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/dxf.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/el.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/elf.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/eml.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/enc.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/eot.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/eps.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/epub.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/eslintignore.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/exe.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/f4v.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/fax.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/fb2.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/fla.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/flac.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/flv.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/fnt.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/folder-link.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/folder-up.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/folder.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/fon.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/gdp.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/gem.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/gif.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/gitattributes.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/gitignore.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/go.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/gpg.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/gpl.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/gradle.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/gz.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/h.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/handlebars.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/hbs.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/heic.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/hlp.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/hs.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/hsl.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/htm.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/html.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ibooks.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/icns.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ico.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ics.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/idx.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/iff.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ifo.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/image.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/img.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/iml.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/inc.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/indd.svg
1
1
<svg height="64" width="58" xmlns="http://www.w3.org/2000/svg"><path d="M.624 29.625V.725h3.9v28899-4-9.8901zm0 0 stroke-width="1.25" transform="matrix(2.09009 0 0 2.08311 0 .076)"/></svg>
A src/main/resources/com/keenwrite/ui/fonts/icons/inf.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/info.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ini.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/inv.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/iso.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/j2.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/jar.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/java.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/jpg.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/js.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/json.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/jsp.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/jsx.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/key.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/kf8.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/kmk.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ksh.svg
1
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/main/resources/com/keenwrite/ui/fonts/icons/kt.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/kts.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/kup.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/less.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/lex.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/licx.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/lisp.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/lit.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/lnk.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/lock.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/log.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/lua.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/m.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/m2v.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/m3u.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/m3u8.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/m4.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/m4a.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/m4r.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/m4v.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/map.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mc.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/md.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mdb.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mdf.svg
1
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.852d5006e"/></svg>
A src/main/resources/com/keenwrite/ui/fonts/icons/me.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mi.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mid.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/midi.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mk.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mkv.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mm.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mng.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mo.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mobi.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mod.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mov.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mp2.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mp3.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mp4.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mpa.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mpd.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mpe.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mpeg.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mpg.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mpga.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mpp.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/mpt.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/msg.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/msi.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/msu.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/nef.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/nes.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/nfo.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/nix.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/npmignore.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ocx.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/odb.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ods.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/odt.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ogg.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ogv.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ost.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/otf.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ott.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ova.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ovf.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/p12.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/p7b.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/part.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/pdb.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/pdf.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/pem.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/pfx.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/pgp.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ph.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/phar.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/php.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/pid.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/pkg.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/pl.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/plist.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/pm.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/png.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/po.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/pom.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/pot.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/potx.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/pps.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ppsx.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ppt.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/pptm.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/pptx.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/prop.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ps.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ps1.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/psd.svg
1
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.7v12.1m19.5 27.5m0 0miterlimit="10transform="matrix(2.05225 0 0 2.0612 .316 0)"/></svg>
A src/main/resources/com/keenwrite/ui/fonts/icons/psp.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/pst.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/pub.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/py.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/pyc.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/qt.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/r.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ra.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ram.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/rar.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/raw.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/rb.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/rdf.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/rdl.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/reg.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/resx.svg
1
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.852d5006e"/></svg>
A src/main/resources/com/keenwrite/ui/fonts/icons/retry.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/rm.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/rmd.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/rom.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/rpm.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/rpt.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/rsa.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/rss.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/rst.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/rtf.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ru.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/rub.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/rxml.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/sass.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/scss.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/sdf.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/sed.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/sh.svg
1
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/main/resources/com/keenwrite/ui/fonts/icons/sit.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/sitemap.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/skin.svg
1
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.852d5006e"/></svg>
A src/main/resources/com/keenwrite/ui/fonts/icons/sldm.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/sldx.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/sln.svg
1
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.852d5006e"/></svg>
A src/main/resources/com/keenwrite/ui/fonts/icons/sol.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/sphinx.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/sql.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/sqlite.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/step.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/stl.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/svg.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/swd.svg
1
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 999"/></svg>
A src/main/resources/com/keenwrite/ui/fonts/icons/swf.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/swift.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/swp.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/sys.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/tar.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/tax.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/tcsh.svg
1
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/main/resources/com/keenwrite/ui/fonts/icons/tfignore.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/tga.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/tgz.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/tiff.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/tmp.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/tmx.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/torrent.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/tpl.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ts.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/tsv.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/ttf.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/twig.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/txt.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/udf.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/vb.svg
1
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.852d5006e"/></svg>
A src/main/resources/com/keenwrite/ui/fonts/icons/vbs.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/vcd.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/vcf.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/vcs.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/vdi.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/vmdk.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/vob.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/vox.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/vscodeignore.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/war.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/wav.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/wbk.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/webinfo.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/webm.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/webp.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/wma.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/wmf.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/wmv.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/woff.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/woff2.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/wps.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/wsf.svg
1
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/main/resources/com/keenwrite/ui/fonts/icons/xaml.svg
1
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.21.1.6-1.6.6zm25.101 0c-.503 0-1.102-.2-1.502999.6-1.5.6zm-16.7 4.1c-.202 0-.403 0-.7-.1-1.1028.
A src/main/resources/com/keenwrite/ui/fonts/icons/xcf.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/xfl.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/xlm.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/xls.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/xlsm.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/xlsx.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/xlt.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/xltm.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/xltx.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/xml.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/xpi.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/xps.svg
1
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.21.1.6-1.6.6zm25.101 0c-.503 0-1.102-.2-1.502999.6-1.5.6zm-16.7 4.1c-.202 0-.403 0-.7-.1-1.1028.
A src/main/resources/com/keenwrite/ui/fonts/icons/xrb.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/xsd.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/xsl.svg
1
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.21.1.6-1.6.6zm25.101 0c-.503 0-1.102-.2-1.502999.6-1.5.6zm-16.7 4.1c-.202 0-.403 0-.7-.1-1.1028.
A src/main/resources/com/keenwrite/ui/fonts/icons/xspf.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/xz.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/yaml.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/z.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>
12
A src/main/resources/com/keenwrite/ui/fonts/icons/zip.svg
1
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>
A src/main/resources/com/keenwrite/ui/fonts/icons/zsh.svg
1
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/main/resources/com/keenwrite/xml.css
1
.tagmark {
2
    -fx-fill: gray;
3
}
4
.anytag {
5
    -fx-fill: crimson;
6
}
7
.paren {
8
    -fx-fill: firebrick;
9
    -fx-font-weight: bold;
10
}
11
.attribute {
12
    -fx-fill: darkviolet;
13
}
14
.avalue {
15
    -fx-fill: black;
16
}
117
18
.comment {
19
	-fx-fill: teal;
20
}
A src/main/resources/fonts/noto-sans/NotoSans-Bold.ttf
Binary file
A src/main/resources/fonts/noto-sans/NotoSans-BoldItalic.ttf
Binary file
A src/main/resources/fonts/noto-sans/NotoSans-Italic.ttf
Binary file
A src/main/resources/fonts/noto-sans/NotoSans-Regular.ttf
Binary file
A src/main/resources/fonts/source-code-pro/SourceCodePro-Bold.ttf
Binary file
A src/main/resources/fonts/source-code-pro/SourceCodePro-BoldItalic.ttf
Binary file
A src/main/resources/fonts/source-code-pro/SourceCodePro-Italic.ttf
Binary file
A src/main/resources/fonts/source-code-pro/SourceCodePro-Regular.ttf
Binary file
A src/main/resources/fonts/source-serif-4/SourceSerif4-Bold.otf
Binary file
A src/main/resources/fonts/source-serif-4/SourceSerif4-BoldItalic.otf
Binary file
A src/main/resources/fonts/source-serif-4/SourceSerif4-Italic.otf
Binary file
A src/main/resources/fonts/source-serif-4/SourceSerif4-Regular.otf
Binary file
A src/main/resources/lexicons/README.md
1
# Building
2
3
The lexicon files are retrieved from SymSpell in the parent directory:
4
5
svn export \
6
  https://github.com/wolfgarbe/SymSpell/trunk/SymSpell.FrequencyDictionary/ lexicons
7
8
The lexicons and bigrams are both space-separated, but parsing a
9
tab-delimited file is easier, so change them to tab-separated files.
110
A src/main/resources/lexicons/de.txt
Binary file
A src/main/resources/lexicons/en.txt
Binary file
A src/main/resources/lexicons/es.txt
Binary file
A src/main/resources/lexicons/ext/README.md
1
# Overview
2
3
Lexicons in this directory are meant to relate to a particular subject
4
(medicine, chemistry, math, sports, and such), extend the main lexicon,
5
or not be in common use.
6
17
A src/main/resources/lexicons/ext/contractions.txt
11
2
'aight
3
ain't
4
amn't
5
aren't
6
can't
7
'cause
8
couldn't
9
couldn't've
10
could've
11
daren't
12
daresn't
13
dasn't
14
didn't
15
doesn't
16
don't
17
dunno
18
d'ye
19
e'er
20
everybody's
21
everyone's
22
g'day
23
gimme
24
giv'n
25
gonna
26
gon't
27
gotta
28
hadn't
29
had've
30
hasn't
31
haven't
32
he'd
33
he'll
34
he's
35
he've
36
how'd
37
howdy
38
how'll
39
how're
40
how's
41
how've
42
i'd
43
i'dn't've
44
i'd've
45
i'll
46
i'm
47
i'm'a
48
imma
49
innit
50
isn't
51
it'd
52
it'll
53
it's
54
i've
55
let's
56
ma'am
57
mayn't
58
may've
59
methinks
60
mightn't
61
might've
62
mustn't
63
mustn't've
64
must've
65
needn't
66
ne'er
67
o'clock
68
o'er
69
ol'
70
oughtn't
71
shalln't
72
shan't
73
she'd
74
she'll
75
she's
76
shouldn't
77
shouldn't've
78
should've
79
somebody's
80
someone's
81
something's
82
so're
83
that'd
84
that'll
85
that're
86
that's
87
there'd
88
there'll
89
there're
90
there's
91
these'd
92
these'll
93
these're
94
these've
95
they'd
96
they'll
97
they're
98
they've
99
this's
100
those're
101
those've
102
'tis
103
to've
104
'twas
105
'twouldn't
106
wanna
107
wasn't
108
we'd
109
we'd've
110
we'll
111
we're
112
weren't
113
we've
114
what'd
115
what'll
116
what're
117
what's
118
what've
119
when'd
120
when'll
121
when's
122
where'd
123
where'll
124
where're
125
where's
126
where've
127
which'd
128
which'll
129
which're
130
which's
131
which've
132
who'd
133
who'd've
134
who'll
135
who're
136
who's
137
who've
138
why'd
139
why'll
140
why're
141
why's
142
willn't
143
won't
144
wouldn't
145
wouldn't've
146
would've
147
y'all
148
y'all'd've
149
y'all're
150
you'd
151
you'dn't've
152
you'll
153
you're
154
you've
155
A src/main/resources/lexicons/ext/tech.txt
1
analytics	130337
2
hotspot	130022
3
instantiation	130000
4
onboarding	129953
5
biometric	129795
6
anamorphic	129777
7
benchmarking	129772
8
cybersecurity	129769
9
barcode	129757
10
splitter	129755
11
keychain	129719
12
crowdfunding	129696
13
polymorphism	129688
14
automata	129666
15
shockwave	129658
16
profiler	129648
17
kerning	129646
18
nanometer	129630
19
meridiem	129624
20
influencer	129618
21
passcode	129617
22
sexting	129607
23
cryptology	129606
24
biometrics	129606
25
bitcoin	129599
26
specular	129598
27
accelerometer	129588
28
googolplex	129583
29
grayscale	129576
30
ascender	129571
31
pixelated	129569
32
rockstar	129565
33
ragdoll	129564
34
cyberattack	129564
35
cryptanalysis	129562
36
ransomware	129553
37
crowdsourcing	129552
38
hackathon	129551
39
audiobook	129544
40
degauss	129543
41
attenuator	129540
42
jetpack	129538
43
packrat	129536
44
backlight	129535
45
bootable	129530
46
octothorpe	129529
47
newsfeed	129525
48
extranet	129523
49
failover	129516
50
cyberbullying	129516
51
neumann	129515
52
capacitive	129514
53
backlit	129511
54
millimicron	129507
55
inductor	129505
56
workgroup	129502
57
journaling	129500
58
middleware	129499
59
spooler	129497
60
clamshell	129495
61
wireframe	129494
62
modularity	129493
63
strikethrough	129489
64
petabyte	129487
65
jughead	129482
66
acyclic	129482
67
gearhead	129478
68
stateful	129473
69
submenu	129467
70
pseudorandom	129463
71
earbuds	129461
72
narrowband	129460
73
recordable	129457
74
unallocated	129455
75
mappable	129455
76
chipset	129454
77
multicast	129447
78
loopback	129444
79
pixelate	129441
80
cryptographic	129441
81
pixelation	129438
82
autocorrect	129438
83
teraflop	129437
84
digitizer	129436
85
tunnelling	129434
86
deduplication	129434
87
subwoofer	129433
88
touchpad	129429
89
namespace	129428
90
microcontroller	129428
91
geolocation	129428
92
telepresence	129427
93
driverless	129426
94
photolithography	129425
95
multiphase	129425
96
verifier	129424
97
robocall	129424
98
autofocus	129424
99
kilobit	129422
100
hacktivist	129419
101
geocache	129415
102
rasterize	129412
103
plaintext	129411
104
pipelining	129411
105
technobabble	129409
106
defragment	129409
107
connectionless	129409
108
homomorphic	129407
109
demodulator	129406
110
datagram	129406
111
activex	129406
112
normalisation	129404
113
blackhole	129402
114
cyberstalker	129401
115
multifunction	129400
116
undirected	129397
117
ciphertext	129397
118
superspeed	129396
119
spacebar	129395
120
cyberwar	129395
121
borderless	129395
122
transcode	129393
123
cyberbully	129393
124
multimeter	129392
125
dropship	129391
126
yottabyte	129390
127
infector	129390
128
superclass	129389
129
tooltip	129388
130
dereference	129387
131
combinator	129386
132
milliwatt	129385
133
cyberstalking	129384
134
subfolder	129383
135
wideband	129382
136
noncontiguous	129382
137
ferroelectric	129382
138
cybersquatting	129378
139
autofill	129378
140
trackpad	129376
141
associatively	129376
142
luggable	129374
143
seamonkey	129373
144
defragmentation	129373
145
starcraft	129371
146
obliquing	129371
147
leadless	129371
148
greeking	129371
149
upgradeable	129370
150
radiosity	129370
151
transcoding	129369
152
quintillionth	129369
153
bitmapped	129369
154
subdirectory	129368
155
degausser	129368
156
curtiss	129368
157
scunthorpe	129367
158
undelete	129365
159
gigaflops	129365
160
darknet	129365
161
zettabyte	129364
162
topologies	129363
163
spidering	129363
164
photorealism	129363
165
multithreading	129363
166
deallocate	129363
167
mersenne	129362
168
machinima	129361
169
satisfiable	129360
170
laserjet	129360
171
multicore	129359
172
microblog	129359
173
megaflops	129359
174
homeomorphic	129359
175
microblogging	129358
176
kilobaud	129358
177
cyberwarfare	129358
178
microarchitecture	129357
179
autosave	129357
180
wirelessly	129356
181
sneakernet	129355
182
textbox	129354
183
obfuscator	129354
184
microkernel	129353
185
substring	129352
186
macroinstruction	129352
187
endianness	129352
188
indexable	129351
189
backtick	129351
190
unshielded	129350
191
cleartext	129350
192
autocomplete	129349
193
abandonware	129349
194
hacktivism	129348
195
antikythera	129348
196
stereolithography	129347
197
photorealistic	129347
198
macrovision	129347
199
greasemonkey	129347
200
geotagging	129347
201
disassembler	129346
202
spacewar	129345
203
pluggable	129345
204
kilobits	129345
205
webcomic	129344
206
unfollow	129344
207
photosensor	129344
208
petaflop	129344
209
garageband	129344
210
truetype	129343
211
subnetwork	129342
212
backpropagation	129342
213
supercomputing	129340
214
smartwatch	129340
215
unbundled	129339
216
smilies	129339
217
milliamp	129339
218
bytecode	129339
219
trackpoint	129337
220
slipstreaming	129337
221
monospace	129337
222
memoization	129337
223
scaleable	129336
224
respawn	129335
225
multicasting	129335
226
geocacher	129335
227
workgroups	129334
228
ferrofluid	129334
229
smartdrive	129333
230
subsampling	129332
231
rasterization	129332
232
guiltware	129332
233
defragger	129332
234
satisfiability	129331
235
activision	129331
236
subdirectories	129330
237
segfault	129330
238
flamebait	129330
239
framebuffer	129329
240
defragging	129329
241
decompiler	129329
242
unshift	129328
243
memristor	129328
244
zebibyte	129327
245
semiprime	129327
246
rotoscoping	129327
247
hypertransport	129327
248
smartmedia	129326
249
grayware	129326
250
defragmenting	129326
251
defragmenter	129326
252
repagination	129325
253
subnetting	129324
254
skeuomorphism	129324
255
screencast	129324
256
stylesheet	129323
257
superintelligence	129322
258
multitenancy	129322
259
datastore	129322
260
autoplay	129322
261
repaginate	129321
262
macbook	129321
263
geotagged	129321
264
baudrate	129321
265
transmeta	129320
266
screwless	129320
267
nameserver	129320
268
interexchange	129320
269
geocoding	129319
270
downloader	129319
271
autodiscovery	129319
272
extortion	65752
273
emoji	65684
274
googol	65618
275
backside	65388
276
fibre	65387
277
metre	65333
278
royale	65173
279
radix	65093
280
hotdog	65091
281
lecher	65062
282
uptime	65009
283
unbound	64979
284
eniac	64975
285
synaptic	64966
286
voxel	64926
287
selfie	64917
288
uplink	64887
289
fanboy	64857
290
defrag	64849
291
nondisclosure	64839
292
qubit	64828
293
yippie	64821
294
gearhead	64819
295
subnet	64818
296
endian	64798
297
bezier	64797
298
reallocation	64796
299
telephonic	64789
300
mosfet	64777
301
mutex	64775
302
inkjet	64772
303
gobbing	64768
304
shader	64766
305
ultralight	64755
306
hackers	64746
307
pacman	64742
308
unlink	64741
309
undock	64740
310
understroke	64738
311
beginners	64736
312
photoscope	64731
313
gantt	64725
314
programmers	64722
315
todays	64720
316
moores	64716
317
fullscreen	64715
318
moveless	64708
319
reformatted	64704
320
deallocate	64704
321
laserdisc	64702
322
macos	64700
323
nonactive	64697
324
nonadjacent	64696
325
hotfix	64695
326
keylogger	64694
327
geotag	64691
328
oreilly	64681
329
exabit	64678
330
jailbroken	64677
331
fuzzer	64676
332
noninteractive	64673
333
multifactor	64672
334
letterspacing	64671
335
preinstall	64669
336
multiboot	64666
337
runescape	64665
338
micropayment	64664
339
numpad	64663
340
preinstalled	64661
341
jailbreaking	64660
342
attend	2158
343
withstand	1809
344
transpire	1116
345
reading	1110
346
texture	1065
347
capitalize	832
348
calling	779
349
unfold	767
350
starboard	679
351
commode	625
352
doing	594
353
textbook	499
354
unease	378
355
unpack	358
356
keycard	231
357
mainspring	207
358
grr	180
359
geocaching	167
360
microbus	160
361
mp3	147
362
svg	139
363
shifted	128
364
texted	127
365
towheaded	118
366
mineshaft	115
367
nonparty	95
368
crossbite	80
369
resignedness	69
370
msrp	61
371
inbreak	53
372
nanocomposite	44
373
md5	44
374
neomorphic	41
375
superstrain	28
376
lifers	27
377
multination	26
378
smartwatch	22
379
antilibration	22
380
zapf	20
381
mp4	20
1382
A src/main/resources/lexicons/fr.txt
Binary file
A src/main/resources/lexicons/he.txt
Binary file
A src/main/resources/lexicons/it.txt
Binary file
A src/main/resources/lexicons/ru.txt
Binary file
A src/main/resources/lexicons/zh.txt
Binary file
A src/test/java/com/keenwrite/AwaitFxExtension.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite;
3
4
import javafx.embed.swing.JFXPanel;
5
import org.junit.jupiter.api.extension.BeforeAllCallback;
6
import org.junit.jupiter.api.extension.ExtensionContext;
7
import org.testfx.osgi.service.TestFx;
8
9
import java.util.concurrent.Semaphore;
10
11
import static javafx.application.Platform.runLater;
12
import static javax.swing.SwingUtilities.invokeLater;
13
14
/**
15
 * Blocks all unit tests until JavaFX is ready.
16
 */
17
public class AwaitFxExtension implements BeforeAllCallback {
18
  /**
19
   * Prevent {@link RuntimeException} for internal graphics not initialized yet.
20
   *
21
   * @param context Provided by the {@link TestFx} framework.
22
   * @throws InterruptedException Could not acquire semaphore.
23
   */
24
  @Override
25
  public void beforeAll( final ExtensionContext context )
26
    throws InterruptedException {
27
    final var semaphore = new Semaphore( 0 );
28
29
    invokeLater( () -> {
30
      // Prepare JavaFX toolkit and environment.
31
      new JFXPanel();
32
      runLater( semaphore::release );
33
    } );
34
35
    semaphore.acquire();
36
  }
37
}
138
A src/test/java/com/keenwrite/definition/TreeViewTest.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.definition;
3
4
import com.keenwrite.editors.definition.DefinitionEditor;
5
import com.keenwrite.editors.definition.yaml.YamlTreeTransformer;
6
import com.keenwrite.editors.markdown.MarkdownEditor;
7
import com.keenwrite.preferences.Workspace;
8
import com.keenwrite.preview.HtmlPreview;
9
import com.panemu.tiwulfx.control.dock.DetachableTabPane;
10
import javafx.application.Application;
11
import javafx.beans.property.SimpleObjectProperty;
12
import javafx.event.Event;
13
import javafx.event.EventHandler;
14
import javafx.scene.Node;
15
import javafx.scene.Scene;
16
import javafx.scene.control.ColorPicker;
17
import javafx.scene.control.SplitPane;
18
import javafx.scene.control.Tooltip;
19
import javafx.scene.control.TreeItem;
20
import javafx.stage.Stage;
21
import org.testfx.framework.junit5.Start;
22
23
import static com.keenwrite.util.FontLoader.initFonts;
24
25
//@ExtendWith(ApplicationExtension.class)
26
public class TreeViewTest extends Application {
27
  private final SimpleObjectProperty<Node> mTextEditor =
28
    new SimpleObjectProperty<>();
29
30
  private final EventHandler<TreeItem.TreeModificationEvent<Event>> mTreeHandler =
31
    event -> refresh( mTextEditor.get() );
32
33
  private void refresh( final Node node ) {
34
    throw new RuntimeException( "Derp: " + node );
35
  }
36
37
  public static void main( final String[] args ) {
38
    initFonts();
39
    launch( args );
40
  }
41
42
  public void start( final Stage stage ) {
43
    onStart( stage );
44
  }
45
46
  @Start
47
  private void onStart( final Stage stage ) {
48
    final var workspace = new Workspace();
49
    final var mainPane = new SplitPane();
50
51
    final var transformer = new YamlTreeTransformer();
52
    final var editor = new DefinitionEditor( transformer );
53
54
    final var tabPane1 = new DetachableTabPane();
55
    tabPane1.addTab( "Editor", editor );
56
57
    final var tabPane2 = new DetachableTabPane();
58
    final var tab21 = tabPane2.addTab( "Picker", new ColorPicker() );
59
    final var tab22 = tabPane2.addTab( "Editor",
60
                                       new MarkdownEditor( workspace ) );
61
    tab21.setTooltip( new Tooltip( "Colour Picker" ) );
62
    tab22.setTooltip( new Tooltip( "Text Editor" ) );
63
64
    final var tabPane3 = new DetachableTabPane();
65
    tabPane3.addTab( "Preview", new HtmlPreview( workspace ) );
66
67
    editor.addTreeChangeHandler( mTreeHandler );
68
69
    mainPane.getItems().addAll( tabPane1, tabPane2, tabPane3 );
70
71
    final var scene = new Scene( mainPane );
72
    stage.setScene( scene );
73
74
    stage.show();
75
  }
76
}
177
A src/test/java/com/keenwrite/editors/markdown/MarkdownEditorTest.java
1
package com.keenwrite.editors.markdown;
2
3
import com.keenwrite.AwaitFxExtension;
4
import com.keenwrite.preferences.Workspace;
5
import org.junit.jupiter.api.Test;
6
import org.junit.jupiter.api.extension.ExtendWith;
7
import org.testfx.framework.junit5.ApplicationExtension;
8
9
import java.util.regex.Pattern;
10
11
import static java.util.regex.Pattern.compile;
12
import static javafx.application.Platform.runLater;
13
import static org.junit.jupiter.api.Assertions.assertEquals;
14
import static org.junit.jupiter.api.Assertions.assertTrue;
15
16
@ExtendWith( {ApplicationExtension.class, AwaitFxExtension.class} )
17
public class MarkdownEditorTest {
18
  private static final String[] WORDS = new String[]{
19
    "Italicize",
20
    "English's",
21
    "foreign",
22
    "words",
23
    "based",
24
    "on",
25
    "popularity,",
26
    "like",
27
    "_bête_",
28
    "_noire_",
29
    "and",
30
    "_Weltanschauung_",
31
    "but",
32
    "not",
33
    "résumé.",
34
    "Don't",
35
    "omit",
36
    "accented",
37
    "characters!",
38
    "Cœlacanthe",
39
    "L'Haÿ-les-Roses",
40
    "Mühlfeldstraße",
41
    "Da̱nx̱a̱laga̱litła̱n",
42
  };
43
44
  private static final String TEXT = String.join( " ", WORDS );
45
46
  private static final Pattern REGEX = compile(
47
    "[^\\p{Mn}\\p{Me}\\p{L}\\p{N}'-]+" );
48
49
  /**
50
   * Test that the {@link MarkdownEditor} can retrieve a word at the caret
51
   * position, regardless of whether the caret is at the beginning, middle, or
52
   * end of the word.
53
   */
54
  @Test
55
  public void test_CaretWord_GetISO88591Word_WordSelected() {
56
    runLater( () -> {
57
      final var editor = createMarkdownEditor();
58
59
      for( int i = 0; i < WORDS.length; i++ ) {
60
        final var word = WORDS[ i ];
61
        final var len = word.length();
62
        final var expected = REGEX.matcher( word ).replaceAll( "" );
63
64
        for( int j = 0; j < len; j++ ) {
65
          editor.moveTo( offset( i ) + j );
66
          final var actual = editor.getCaretWordText();
67
          assertEquals( expected, actual );
68
        }
69
      }
70
    } );
71
  }
72
73
  /**
74
   * Test that the {@link MarkdownEditor} can make a word bold.
75
   */
76
  @Test
77
  public void test_CaretWord_SetWordBold_WordIsBold() {
78
    final var index = 20;
79
    final var editor = createMarkdownEditor();
80
81
    editor.moveTo( offset( index ) );
82
    editor.bold();
83
    assertTrue( editor.getText().contains( "**" + WORDS[ index ] + "**" ) );
84
  }
85
86
  /**
87
   * Returns the document offset for a string at the given index.
88
   */
89
  private static int offset( final int index ) {
90
    assert 0 <= index && index < WORDS.length;
91
    int offset = 0;
92
93
    for( int i = 0; i < index; i++ ) {
94
      offset += WORDS[ i ].length();
95
    }
96
97
    // Add the index to compensate for one space between words.
98
    return offset + index;
99
  }
100
101
  /**
102
   * Returns an instance of {@link MarkdownEditor} pre-populated with
103
   * {@link #TEXT}.
104
   *
105
   * @return A new {@link MarkdownEditor} instance, ready for unit tests.
106
   */
107
  private MarkdownEditor createMarkdownEditor() {
108
    final var workspace = new Workspace();
109
    final var editor = new MarkdownEditor( workspace );
110
    editor.setText( TEXT );
111
    return editor;
112
  }
113
}
1114
A src/test/java/com/keenwrite/io/FileWatchServiceTest.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.io;
3
4
import org.junit.jupiter.api.Test;
5
import org.junit.jupiter.api.Timeout;
16
7
import java.io.File;
8
import java.io.IOException;
9
import java.file.Files.write( f )write( file.toPath(), text.getBytes()
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;
16
7
import static com.keenwrite.io.MediaTypeExtension.valueFrom;
8
import static org.apache.commons.io.FilenameUtils.getExtension;
9
import static org.junit.jupiter.api.Assertion*      final var files = path.listFiles();
10
      assertNotNull( filesfiles
A src/test/java/com/keenwrite/io/MediaTypeTest.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.io;
3
4
import org.junit.jupiter.api.Test;
15
6
import HttpFacade.httpGet;remote fetches type of resource
7
   * (or shallow decoding)placekitten.com/g/200/300", IMAGE_JPEGIMAGE_SVG_XML( var response = httpGet( new URI( k ) ) )response.getMediaType(
A src/test/java/com/keenwrite/processors/markdown/ImageLinkExtensionTest.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors.markdown;
3
4
import com.keenwrite.AwaitFxExtension;
5
import com.keenwrite.Caret;
6
import com.keenwrite.preferences.Workspace;
7
import com.keenwrite.preview.HtmlPreview;
8
import com.keenwrite.processors.Processor;
9
import com.keenwrite.processors.ProcessorContext;
10
import com.keenwrite.processors.markdown.extensions.ImageLinkExtension;
11
import com.vladsch.flexmark.html.HtmlRenderer;
12
import com.vladsch.flexmark.parser.Parser;
13
import javafx.stage.Stage;
14
import org.junit.jupiter.api.Test;
15
import org.junit.jupiter.api.extension.ExtendWith;
16
import org.testfx.framework.junit5.ApplicationExtension;
17
import org.testfx.framework.junit5.Start;
18
19
import java.io.File;
20
import java.net.URI;
21
import java.net.URL;
22
import java.nio.file.Path;
23
import java.nio.file.Paths;
24
import java.util.HashMap;
25
import java.util.List;
26
import java.util.Map;
27
28
import static com.keenwrite.constants.Constants.DOCUMENT_DEFAULT;
29
import static com.keenwrite.ExportFormat.NONE;
30
import static java.lang.String.format;
31
import static javafx.application.Platform.runLater;
32
import static org.junit.jupiter.api.Assertions.assertEquals;
33
import static org.junit.jupiter.api.Assertions.assertNotNull;
34
import static org.testfx.util.WaitForAsyncUtils.waitForFxEvents;
35
36
/**
37
 * Responsible for testing that linked images render into HTML according to
38
 * the {@link ImageLinkExtension} rules.
39
 */
40
@ExtendWith( {ApplicationExtension.class, AwaitFxExtension.class} )
41
@SuppressWarnings( "SameParameterValue" )
42
public class ImageLinkExtensionTest {
43
  private static final Workspace sWorkspace = new Workspace(
44
    getResource( "workspace.xml" ) );
45
46
  private static final Map<String, String> IMAGES = new HashMap<>();
47
48
  private static final String URI_WEB = "placekitten.com/200/200";
49
  private static final String URI_DIRNAME = "images";
50
  private static final String URI_FILENAME = "kitten";
51
52
  /**
53
   * Path to use for testing image file name resolution. Note that resources use
54
   * forward slashes, regardless of OS.
55
   */
56
  private static final String URI_PATH = URI_DIRNAME + '/' + URI_FILENAME;
57
58
  /**
59
   * Extension for the first existing image that matches the preferred image
60
   * extension order.
61
   */
62
  private static final String URI_IMAGE_EXT = ".png";
63
64
  /**
65
   * Relative path to an image that exists.
66
   */
67
  private static final String URI_IMAGE = URI_PATH + URI_IMAGE_EXT;
68
69
  static {
70
    addUri( URI_PATH + ".png" );
71
    addUri( URI_PATH + ".jpg" );
72
    addUri( URI_PATH, getResource( URI_PATH + URI_IMAGE_EXT ) );
73
    addUri( "//" + URI_WEB );
74
    addUri( "http://" + URI_WEB );
75
    addUri( "https://" + URI_WEB );
76
  }
77
78
  private HtmlPreview mPreview;
79
80
  @Start
81
  @SuppressWarnings( "unused" )
82
  private void start( final Stage stage ) {
83
    mPreview = new HtmlPreview( sWorkspace );
84
  }
85
86
  private static void addUri( final String actualExpected ) {
87
    addUri( actualExpected, actualExpected );
88
  }
89
90
  private static void addUri( final String actual, final String expected ) {
91
    IMAGES.put( toMd( actual ), toHtml( expected ) );
92
  }
93
94
  private static String toMd( final String resource ) {
95
    return format( "![Tooltip](%s 'Title')", resource );
96
  }
97
98
  private static String toHtml( final String url ) {
99
    return format(
100
      "<p><img src=\"%s\" alt=\"Tooltip\" title=\"Title\" /></p>\n", url );
101
  }
102
103
  /**
104
   * Test that the key URIs present in the {@link #IMAGES} map are rendered
105
   * as the value URIs present in the same map.
106
   */
107
  @Test
108
  void test_ImageLookup_RelativePathWithExtension_ResolvedSuccessfully() {
109
    final var resource = getResourcePath( URI_IMAGE );
110
    final var imagePath = new File( URI_IMAGE ).toPath();
111
    final var subpaths = resource.getNameCount() - imagePath.getNameCount();
112
    final var subpath = resource.subpath( 0, subpaths );
113
114
    // The root component isn't considered part of the path, so add it back.
115
    final var documentPath = Path.of(
116
      resource.getRoot().resolve( subpath ).toString(),
117
      DOCUMENT_DEFAULT.getName() );
118
    final var context = createProcessorContext( documentPath );
119
    final var extension = ImageLinkExtension.create( context );
120
    final var extensions = List.of( extension );
121
    final var pBuilder = Parser.builder();
122
    final var hBuilder = HtmlRenderer.builder();
123
    final var parser = pBuilder.extensions( extensions ).build();
124
    final var renderer = hBuilder.extensions( extensions ).build();
125
126
    assertNotNull( parser );
127
    assertNotNull( renderer );
128
129
    for( final var entry : IMAGES.entrySet() ) {
130
      final var key = entry.getKey();
131
      final var node = parser.parse( key );
132
      final var expectedHtml = entry.getValue();
133
      final var actualHtml = new StringBuilder( 128 );
134
135
      runLater( () -> actualHtml.append( renderer.render( node ) ) );
136
137
      waitForFxEvents();
138
      assertEquals( expectedHtml, actualHtml.toString() );
139
    }
140
  }
141
142
  /**
143
   * Creates a new {@link ProcessorContext} for the given file name path.
144
   *
145
   * @param documentPath Fully qualified path to the file name.
146
   * @return A context used for creating new {@link Processor} instances.
147
   */
148
  private ProcessorContext createProcessorContext( final Path documentPath ) {
149
    return new ProcessorContext(
150
      mPreview,
151
      new HashMap<>(),
152
      documentPath,
153
      null,
154
      NONE,
155
      sWorkspace,
156
      Caret.builder().build()
157
    );
158
  }
159
160
  private static URL toUrl( final String path ) {
161
    final var clazz = ImageLinkExtensionTest.class;
162
    final var packagePath = clazz.getPackageName().replace( '.', '/' );
163
    final var resourcePath = '/' + packagePath + '/' + path;
164
    return clazz.getResource( resourcePath );
165
  }
166
167
  private static URI toUri( final String path ) {
168
    try {
169
      return toUrl( path ).toURI();
170
    } catch( final Exception ex ) {
171
      throw new RuntimeException( ex );
172
    }
173
  }
174
175
  private static Path getResourcePath( final String path ) {
176
    return Paths.get( toUri( path ) );
177
  }
178
179
  private static String getResource( final String path ) {
180
    return toUri( path ).toString();
181
  }
182
}
1183
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;
110
11
import static orgDisabled
12
  @SuppressWarnings( "unused" )
A src/test/java/com/keenwrite/r/PluralizeTest.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.r;
3
4
import org.junit.jupiter.api.BeforeAll;
5
import org.junit.jupiter.api.Test;
16
7
import javax.script.ScriptEngine;
8
import javax.script.ScriptEngineManager;
9
import
A src/test/java/com/keenwrite/sigils/RSigilOperatorTest.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.sigils;
3
4
import javafx.beans.property.SimpleStringProperty;
5
import javafx.beans.property.StringProperty;
6
import org.junit.jupiter.api.Test;
7
8
import static org.junit.jupiter.api.Assertions.assertEquals;
9
10
/**
11
 * Responsible for simulating R variable injection.
12
 */
13
class RSigilOperatorTest {
14
15
  private final SigilOperator mOperator = createRSigilOperator();
16
17
  /**
18
   * Test that a key name becomes an R variable.
19
   */
20
  @Test
21
  void test_Entoken_KeyName_Tokenized() {
22
    final var expected = "v$a$b$c$d";
23
    final var actual = mOperator.entoken( "{{a.b.c.d}}" );
24
    assertEquals( expected, actual );
25
  }
26
27
  /**
28
   * Test that a key name becomes a viable R expression.
29
   */
30
  @Test
31
  void test_Apply_KeyName_Expression() {
32
    final var expected = "`r#x(v$a$b$c$d)`";
33
    final var actual = mOperator.apply( "v$a$b$c$d" );
34
    assertEquals( expected, actual );
35
  }
36
37
  private StringProperty createToken( final String token ) {
38
    return new SimpleStringProperty( token );
39
  }
40
41
  private Tokens createRTokens() {
42
    return createTokens( "x(", ")" );
43
  }
44
45
  private Tokens createYamlTokens() {
46
    return createTokens( "{{", "}}" );
47
  }
48
49
  private Tokens createTokens( final String began, final String ended ) {
50
    return new Tokens( createToken( began ), createToken( ended ) );
51
  }
52
53
  private YamlSigilOperator createYamlSigilOperator() {
54
    return new YamlSigilOperator( createYamlTokens() );
55
  }
56
57
  private RSigilOperator createRSigilOperator() {
58
    return new RSigilOperator( createRTokens(), createYamlSigilOperator() );
59
  }
60
}
161
A src/test/java/com/keenwrite/tex/TeXRasterization.java
1
/*
2
 * Copyright 2020-2021 White Magic Software, Ltd.
3
 *
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions are met:
8
 *
9
 *  o Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 *
12
 *  o Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (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.
27
 */
28
package com.keenwrite.tex;
29
30
import com.whitemagicsoftware.tex.DefaultTeXFont;
31
import com.whitemagicsoftware.tex.TeXEnvironment;
32
import com.whitemagicsoftware.tex.TeXFormula;
33
import com.whitemagicsoftware.tex.TeXLayout;
34
import com.whitemagicsoftware.tex.graphics.AbstractGraphics2D;
35
import com.whitemagicsoftware.tex.graphics.SvgDomGraphics2D;
36
import com.whitemagicsoftware.tex.graphics.SvgGraphics2D;
37
import org.apache.batik.transcoder.TranscoderException;
38
import org.junit.jupiter.api.Test;
39
import org.xml.sax.SAXException;
40
41
import javax.imageio.ImageIO;
42
import javax.xml.parsers.DocumentBuilderFactory;
43
import javax.xml.parsers.ParserConfigurationException;
44
import java.awt.image.BufferedImage;
45
import java.io.ByteArrayInputStream;
46
import java.io.File;
47
import java.io.IOException;
48
import java.nio.file.Path;
49
import java.text.ParseException;
50
51
import static com.keenwrite.preview.SvgRasterizer.*;
52
import static java.lang.System.getProperty;
53
import static org.junit.jupiter.api.Assertions.assertEquals;
54
55
/**
56
 * Test that TeX rasterization produces a readable image.
57
 */
58
public class TeXRasterization {
59
  private static final String LOAD_EXTERNAL_DTD =
60
      "http://apache.org/xml/features/nonvalidating/load-external-dtd";
61
62
  private static final String EQUATION =
63
      "G_{\\mu \\nu} = \\frac{8 \\pi G}{c^4} T_{{\\mu \\nu}}";
64
65
  private static final String DIR_TEMP = getProperty( "java.io.tmpdir" );
66
67
  private static final long FILESIZE = 12364;
68
69
  /**
70
   * Test that an equation can be converted to a raster image and the
71
   * final raster image size corresponds to the input equation. This is
72
   * a simple way to verify that the rasterization process is correct,
73
   * albeit if any aspect of the SVG algorithm changes (such as padding
74
   * around the equation), it will cause this test to fail, which is a bit
75
   * misleading.
76
   */
77
  @Test
78
  public void test_Rasterize_SimpleFormula_CorrectImageSize()
79
    throws IOException, ParseException, TranscoderException {
80
    final var g = new SvgGraphics2D();
81
    drawGraphics( g );
82
    verifyImage( rasterizeString( g.toString() ) );
83
  }
84
85
  /**
86
   * Test that an SVG document object model can be parsed and rasterized into
87
   * an image.
88
   */
89
  @Test
90
  public void getTest_SvgDomGraphics2D_InputElement_OutputRasterizedImage()
91
    throws ParserConfigurationException, IOException, SAXException,
92
    ParseException, TranscoderException {
93
    final var g = new SvgGraphics2D();
94
    drawGraphics( g );
95
96
    final var expectedSvg = g.toString();
97
    final var bytes = expectedSvg.getBytes();
98
99
    final var dbf = DocumentBuilderFactory.newInstance();
100
    dbf.setFeature( LOAD_EXTERNAL_DTD, false );
101
    dbf.setNamespaceAware( false );
102
    final var builder = dbf.newDocumentBuilder();
103
104
    final var doc = builder.parse( new ByteArrayInputStream( bytes ) );
105
    final var actualSvg = toSvg( doc.getDocumentElement() );
106
107
    verifyImage( rasterizeString( actualSvg ) );
108
  }
109
110
  /**
111
   * Test that an SVG image from a DOM element can be rasterized.
112
   *
113
   * @throws IOException Could not write the image.
114
   */
115
  @Test
116
  public void test_SvgDomGraphics2D_InputDom_OutputRasterizedImage()
117
    throws IOException, ParseException, TranscoderException {
118
    final var g = new SvgDomGraphics2D();
119
    drawGraphics( g );
120
121
    final var dom = g.toDom();
122
123
    verifyImage( rasterize( dom ) );
124
  }
125
126
  /**
127
   * Asserts that the given image matches an expected file size.
128
   *
129
   * @param image The image to check against the file size.
130
   * @throws IOException Could not write the image.
131
   */
132
  private void verifyImage( final BufferedImage image ) throws IOException {
133
    final var file = export( image, "dom.png" );
134
    assertEquals( FILESIZE, file.length() );
135
  }
136
137
  /**
138
   * Creates an SVG string for the default equation and font size.
139
   */
140
  private void drawGraphics( final AbstractGraphics2D g ) {
141
    final var size = 100f;
142
    final var texFont = new DefaultTeXFont( size );
143
    final var env = new TeXEnvironment( texFont );
144
    g.scale( size, size );
145
146
    final var formula = new TeXFormula( EQUATION );
147
    final var box = formula.createBox( env );
148
    final var layout = new TeXLayout( box, size );
149
150
    g.initialize( layout.getWidth(), layout.getHeight() );
151
    box.draw( g, layout.getX(), layout.getY() );
152
  }
153
154
  @SuppressWarnings("SameParameterValue")
155
  private File export( final BufferedImage image, final String filename )
156
      throws IOException {
157
    final var path = Path.of( DIR_TEMP, filename );
158
    final var file = path.toFile();
159
    ImageIO.write( image, "png", file );
160
    file.deleteOnExit();
161
    return file;
162
  }
163
}
1164
A src/test/java/com/keenwrite/util/AlphanumComparatorTest.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.util;
3
4
import org.junit.jupiter.api.Test;
5
6
import java.util.ArrayList;
7
import java.util.Arrays;
8
import java.util.Collections;
9
10
import static org.junit.jupiter.api.Assertions.assertEquals;
11
12
/**
13
 * Responsible for testing the http://www.davekoelle.com/alphanum.html
14
 * implementation.
15
 */
16
class AlphanumComparatorTest {
17
18
  /**
19
   * Test that a randomly sorted list containing a mix of alphanumeric
20
   * characters ("chunks") will be sorted according to numeric and alphabetic
21
   * order.
22
   */
23
  @Test
24
  public void test_Sort_UnsortedList_SortedAlphanumerically() {
25
    final var expected = Arrays.asList(
26
      "10X Radonius",
27
      "20X Radonius",
28
      "20X Radonius Prime",
29
      "30X Radonius",
30
      "40X Radonius",
31
      "200X Radonius",
32
      "1000X Radonius Maximus",
33
      "Allegia 6R Clasteron",
34
      "Allegia 50 Clasteron",
35
      "Allegia 50B Clasteron",
36
      "Allegia 51 Clasteron",
37
      "Allegia 500 Clasteron",
38
      "Alpha 2",
39
      "Alpha 2A",
40
      "Alpha 2A-900",
41
      "Alpha 2A-8000",
42
      "Alpha 100",
43
      "Alpha 200",
44
      "Callisto Morphamax",
45
      "Callisto Morphamax 500",
46
      "Callisto Morphamax 600",
47
      "Callisto Morphamax 700",
48
      "Callisto Morphamax 5000",
49
      "Callisto Morphamax 6000 SE",
50
      "Callisto Morphamax 6000 SE2",
51
      "Callisto Morphamax 7000",
52
      "Xiph Xlater 5",
53
      "Xiph Xlater 40",
54
      "Xiph Xlater 50",
55
      "Xiph Xlater 58",
56
      "Xiph Xlater 300",
57
      "Xiph Xlater 500",
58
      "Xiph Xlater 2000",
59
      "Xiph Xlater 5000",
60
      "Xiph Xlater 10000"
61
    );
62
    final var actual = new ArrayList<>( expected );
63
64
    Collections.shuffle( actual );
65
    actual.sort( new AlphanumComparator<>() );
66
    assertEquals( expected, actual );
67
  }
68
}
169
A src/test/java/com/keenwrite/util/CyclicIteratorTest.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.util;
3
4
import org.junit.jupiter.api.Test;
5
6
import java.util.List;
7
import java.util.ListIterator;
8
import java.util.NoSuchElementException;
19
10
import static org.juni
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/processors/markdown/images/kitten.jpg
Binary file
A src/test/resources/com/keenwrite/processors/markdown/images/kitten.png
Binary file
A src/test/resources/com/keenwrite/processors/markdown/workspace.xml
1
<?xml version="1.0" encoding="UTF-8"?>
2
<keenwrite>
3
   <workspace>
4
      <images>
5
         <order>svg pdf png jpg tiff</order>
6
         <dir></dir>
7
      </images>
8
   </workspace>
9
</keenwrite>
110
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 pl&rdquo;
8
\"Hello!\"
9
&ldquo;Hello!&rdquo;
10
11
ma'am
12
ma&apos;am
13
14
'Twas midnight
15
&apos;Twas midnight
16
17
\"Hello,\" said the spider. \"'Shelob' is my name.\"
18
&ldquo;Hello,&rdquo; said the spider. &ldquo;&lsquo;Shelob&rsquo; is my name.&rdquo;
19
20
'A', 'B', and 'C' are letters.
21
&lsquo;A&rsquo; &lsquo;B&rsquo; and &lsquo;C&rsquo; are letters.
22
23
'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'
24
&lsquo;Oak,&rsquo; &lsquo;elm,&rsquo; and &lsquo;beech&rsquo; are names of trees. So is &lsquo;pine.&rsquo;
25
26
'He said, \"I want to go.\"' Were you alive in the 70's?
27
&lsquo;He said, &ldquo;I want to go.&rdquo;&rsquo; Were you alive in the 70&apos;s?
28
29
\"That's a 'magic' sock.\"
30
&ldquo;That&apos;s a &lsquo;magic&rsquo; sock.&rdquo;
31
32
Website! Company Name, Inc. (\"Company Name\" or \"Company\") recommends reading the following terms and conditions, carefully:
33
Website! Company Name, Inc. (&ldquo;Company Name&rdquo; or &ldquo;Company&rdquo;) recommends reading the following terms and conditions, carefully:
34
35
Website! Company Name, Inc. ('Company Name' or 'Company') recommends reading the following terms and conditions, carefully:
36
Website! Company Name, Inc. (&lsquo;Company Name&rsquo; or &lsquo;Company&rsquo;) recommends reading the following terms and conditions, carefully:
37
38
Workin' hard
39
Workin&apos; hard
40
41
'70s are my favorite numbers,' she said.
42
&lsquo;70s are my favorite numbers,&rsquo; she said.
43
44
'70s fashion was weird.
45
&apos;70s fashion was weird.
46
47
12\" record, 5'10\" height
48
12&Prime; record, 5&prime;10&Prime; height
49
50
Model \"T2000\"
51
Model &ldquo;T2000&rdquo;
52
53
iPad 3's battery life is not great.
54
iPad 3&apos;s battery life is not great.
55
56
Book 'em, Danno. Rock 'n' roll. 'Cause 'twas the season.
57
Book &apos;em, Danno. Rock &apos;n&apos; roll. &apos;Cause &apos;twas the season.
58
59
'85 was a good year. (The entire '80s were.)
60
&apos;85 was a good year. (The entire &apos;80s were.)
61
162
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 fiRuns all scripts
6
import s01
7
import s02
8
import s03
9
import s04
110
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 fiintroduces the editor and its purpose.
6
# Fresh start
7
rm( app_home + "/variables.yaml" )
8
rm( app_home + "/untitled.md" )
9
rm( dir_home + "/.scrivenvar
10
# Wait for application to launch
11
openApp( "java -jar " + app_bin )
12
13
wait("1594187265140.png", 30)
14
15
# Breathing room for video recording.
16
wait( 4 )
17
18
# ---------
19
# Introduc240 )
20
21
heading( "What is this application?" )
22
typer( "Well, this application is a text editor that supports interpolated definitions, ")
23
typer( "a few different text formats, real-time preview, spell check ") 
24
typer( "as you tipe" ) 
25
wait( 0.5 )
26
recur( 3ype, and R statements." )
27
paragraph()
28
wait( 1finition demo
29
heading( "What are definitions?" )
30
typer( "Watch. " )
31
wait( .5 )
32
33
# Focus the definition editor.
34
click_create()
35
recur( 4, tab )
36
37
wait( .5application" )
38
title" )
39
Scrivenvar" )
40
41
# Set focus to the text editor.
42
tab()
43
44
typer( "The left-hand pane contains a nested, folder-like structure of names " )
45
typer( "and values that are called *definitions*. " )
46
wait( .5 )
47
typer( "Such definitions can simplify updating documents. " )
48
wait( 1 )
49
50
edit_find( "this application" )
51
typer( "$application.title$" )
52
53
edit_find_next()
54
typer( "$application.title$" )
55
typer( "Tresult after having substituted definition " )
56
typer( "values into the document." ) 
57
Now nobody wants to type definition names all the time. Instead, type any " )
58
typer( "partial definition value followed by `Ctrl+Space`, such as: scr" )
59
wait( 0.5 )
60
autoinsert()
61
wait( 1 )
62
typer( ". *Much* better!" )
63
paragraph()
64
65
heading( "What is interpolation?" )
66
typer( "Definition values can reference definition names. " )
67
wait( .5 )
68
typer( "The definition names act as placeholders. Substituting placeholders with " )
69
typer( "their definition value is called *interpolation*. Let's see how it works." )
70
wait( 2 )
171
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 fihow to use interpolated strings.Open sample chapter.1 )
6
typer( Key.END1O1Edit the sample document.80 )
7
2, down )
8
9
# Grey
10
recur( 3, skip_right )
11
autoinsert()
12
13
# 34
14
recur( 4, skip_right )
15
autoinsert()
16
17
# Central
18
recur( 10, skip_right )
19
autoinsert()
20
21
# London
22
skip_right()
23
autoinsert()
24
25
# Hatchery
26
skip_right()
27
autoinsert()
28
29
# and Conditioning
30
recur( 2, select_word_right )
31
delete()
32
33
# Centre
34
skip_right()
35
autoinsert(
36
typer( " Let's interpolate those four definitions instead!" )
37
wait( 4 )
38
recur( 13, type, Key.BACKSPACE9, backspace60 )
39
40
typer( "name$" )
41
wait( 2 )
42
43
# Collapse all definitions
44
tab()
45
recur( 8, typer, Key.LEFT )
46
47
# Expand to city
48
recur( 4, typer, Key.RIGHT )
49
50
# Jump to name
51
recur( 2, down )
52
recur( 2, typer, Key.RIGHT )
53
54
# Open the text field to show the full value
55
typer( Key.F2 )
56
57
# Traverse the text field
58
home()
59
recur( 16, type, Key.RIGHT, Key.CTRL )
60
esc()
61
62
restore_typing_speed()
63
64
tab()
65
type(_next()
66
typertyper( "'s" )
67
68
edit_find( "Hatcheries" )
69
autoinsert()
70
71
# and Conditioning
72
recur( 2, select_word_right )
73
delete()
74
75
edit_find( "Central" )
76
autoinsert()
77
78
skip_right()
79
autoinsert()
80
81
typer( " How about a different city?" )
82
wait( 2 )
83
recur( 5, type, Key.BACKSPACE, Key.CTRL )
84
wait( 1 )
85
tab()
86
typer( Key.F2 )
87
typer( "Seattle" )
88
enter()
89
tab()
90
wait( 2 )
91
No?" )
92
paragraph()
93
94
tab()
95
typer( Key.F2 )
96
typer( "London" )
97
enter()
98
99
tab()
100
typer( "Organizing definitions is left to your ")
101
typer( "doub" )
102
autoinsert()
103
typer( " Good imagination." )
104
tab()
105
106
# Jump to "char" definition
107
home()
108
109
# Jump to "char.a.primary.name" definition
110
recur( 6, typer, Key.RIGHT )
111
112
# Jump to "char.a.primary.caste" definition
113
down()
114
typer( Key.RIGHT )
115
116
# Jump to root-level "caste" definition
117
recur( 7, down )
118
119
# Reselect "super"
120
recur( 5, typer, Key.RIGHT )
121
wait( 2 )
122
123
# Close the window, no save
124
type( "w0.5 )
125
tab()
126
wait( 0.5 )
127
typer( Key.SPACE )
128
wait( 1 )
1129
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
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 fityping_speed = 80
6
 *args