diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml
index d3a8722..3af025f 100644
--- a/.github/workflows/python-app.yml
+++ b/.github/workflows/python-app.yml
@@ -44,6 +44,7 @@ jobs:
xcopy Convert2EBRL.dist output\Convert2EBRL\Convert2EBRL.dist /S /I
xcopy gui\icons output\Convert2EBRL\icons /S /I
copy gui\conveyor.conf output\Convert2EBRL\conveyor.conf
+ copy vendor\liblouis\COPYING.LESSER output\Convert2EBRL\Convert2EBRL.dist\louis\COPYING.LESSER
- name: Create release zip
run: Compress-Archive -Path output\\Convert2EBRL -Destination convert2ebrl-continuous.zip
- name: Update continuous tag
diff --git a/README.md b/README.md
index 3d6f046..7b0bc7b 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,7 @@ A set of tools for converting documents to eBraille. This repository contains a
* gui: A graphical tool for converting BRF documents into eBraille.
* brf2ebrl: The parser library for converting documents.
* plugins: Subprojects within this directory are parser plugins for specific Braille codes.
+* vendor/liblouis: A vendored copy of liblouis used by brf2ebrl for back-translation, see [vendor/liblouis/README.md](vendor/liblouis/README.md).
## Development status
diff --git a/brf2ebrl/pyproject.toml b/brf2ebrl/pyproject.toml
index b0cb7a4..79d1ed9 100644
--- a/brf2ebrl/pyproject.toml
+++ b/brf2ebrl/pyproject.toml
@@ -12,6 +12,7 @@ dependencies = [
"pypdf>=6.13.3",
"lxml>=6.1.0",
"html5lib>=1.1",
+ "liblouis",
]
requires-python = ">=3.12"
readme = "README.md"
@@ -36,3 +37,6 @@ testpaths = ["tests",]
[build-system]
requires = ["uv_build>=0.11.3,<0.12.0"]
build-backend = "uv_build"
+
+[tool.uv.sources]
+liblouis = { workspace = true }
diff --git a/brf2ebrl/src/brf2ebrl/plugin.py b/brf2ebrl/src/brf2ebrl/plugin.py
index 5d70869..8fc69b1 100644
--- a/brf2ebrl/src/brf2ebrl/plugin.py
+++ b/brf2ebrl/src/brf2ebrl/plugin.py
@@ -24,6 +24,7 @@
from brf2ebrl.parser import Parser
from brf2ebrl.utils import list_sub_paths
+from brf2ebrl.utils.back_translation import back_translate_page_number
from brf2ebrl.utils.ebrl import create_navigation_html, PageRef, HeadingRef
from brf2ebrl.utils.metadata import DEFAULT_METADATA, MetadataItem, ensure_default_metadata
from brf2ebrl.utils.opf import PACKAGE, METADATA, MANIFEST, SPINE, ITEM, ITEMREF, META, FORMAT, DATE
@@ -149,8 +150,10 @@ def _create_navigation_html(self, opf_name: str) -> str:
_HEADING_TAGS.index(element.tag) + 1)))
elif element.tag == "span" and element.get("role") == "doc-pagebreak":
page_id = element.get("id")
+ page_num_braille = element.text_content()
page_refs.append(
- PageRef(href=f"{vol_name}#{page_id}", page_num_braille=element.text_content(), title=""))
+ PageRef(href=f"{vol_name}#{page_id}", page_num_braille=page_num_braille,
+ title=back_translate_page_number(page_num_braille)))
if detected_title is None:
detected_title = ""
return create_navigation_html(opf_name=opf_name, page_refs=page_refs, heading_refs=headings,
diff --git a/brf2ebrl/src/brf2ebrl/utils/back_translation.py b/brf2ebrl/src/brf2ebrl/utils/back_translation.py
new file mode 100644
index 0000000..532e956
--- /dev/null
+++ b/brf2ebrl/src/brf2ebrl/utils/back_translation.py
@@ -0,0 +1,24 @@
+# Copyright (c) 2026. American Printing House for the Blind.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at https://mozilla.org/MPL/2.0/.
+"""Back-translation of braille to print using liblouis."""
+import logging
+from functools import cache
+
+import louis
+from louis.bundled import table_path
+
+# Page numbers are uncontracted, and grade 2 would back-translate roman numerals such as ⠭ and ⠇ as "it" and "like".
+_PAGE_NUMBER_TABLES = [table_path("unicode.dis"), table_path("en-ueb-g1.ctb")]
+
+
+@cache
+def back_translate_page_number(page_num_braille: str) -> str:
+ """Back-translate a Unicode braille page number to its print equivalent."""
+ print_page_num = louis.backTranslateString(_PAGE_NUMBER_TABLES, page_num_braille.strip()).strip()
+ # liblouis marks braille it cannot back-translate as \dots/ or with private use characters.
+ if "\\" in print_page_num or any("" <= c <= "" for c in print_page_num):
+ logging.warning(f"Page number {page_num_braille} could not be fully back-translated, got {print_page_num!r}")
+ return print_page_num
diff --git a/brf2ebrl/src/brf2ebrl/utils/ebrl.py b/brf2ebrl/src/brf2ebrl/utils/ebrl.py
index afa4b10..5ed74af 100644
--- a/brf2ebrl/src/brf2ebrl/utils/ebrl.py
+++ b/brf2ebrl/src/brf2ebrl/utils/ebrl.py
@@ -92,7 +92,7 @@ def create_navigation_html(title: str = "-", braille_title: str = "⠤", heading
ATTR(hidden=""),
H2("⠠⠇⠊⠌ ⠷ ⠏⠁⠛⠑⠎"),
OL(
- *[LI(A(ATTR(href=r.href), r.page_num_braille)) for r in page_refs]
+ *[LI(A(ATTR(href=r.href, title=r.title), r.page_num_braille)) for r in page_refs]
)
)
)
diff --git a/brf2ebrl/tests/test_back_translation.py b/brf2ebrl/tests/test_back_translation.py
new file mode 100644
index 0000000..12d5e49
--- /dev/null
+++ b/brf2ebrl/tests/test_back_translation.py
@@ -0,0 +1,40 @@
+# Copyright (c) 2026. American Printing House for the Blind.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+import lxml.html
+import pytest
+
+from brf2ebrl.utils.back_translation import back_translate_page_number
+from brf2ebrl.utils.ebrl import create_navigation_html, PageRef
+
+
+@pytest.mark.parametrize("page_num_braille,expected", [
+ ("⠼⠁", "1"),
+ ("⠼⠁⠚⠚", "100"),
+ ("⠊", "i"),
+ ("⠭⠊⠧", "xiv"),
+ ("⠭", "x"),
+ ("⠇", "l"),
+ ("⠠⠺⠼⠁", "W1"),
+ ("⠁⠼⠃", "a2"),
+ ("⠼⠁⠤⠼⠃", "1-2"),
+ (" ⠼⠉ ", "3"),
+])
+def test_back_translate_page_number(page_num_braille: str, expected: str):
+ assert back_translate_page_number(page_num_braille) == expected
+
+
+def test_navigation_page_list_has_print_page_title():
+ nav = create_navigation_html(page_refs=[
+ PageRef(href="ebraille/vol0.html#page_1", title="i", page_num_braille="⠊"),
+ PageRef(href="ebraille/vol0.html#page_2", title="1", page_num_braille="⠼⠁"),
+ ])
+ root = lxml.html.fromstring(nav.encode("utf-8"), parser=lxml.html.xhtml_parser)
+ links = root.xpath("//*[@role='doc-pagelist']//*[local-name()='a']")
+ assert [(a.get("href"), a.get("title"), a.text) for a in links] == [
+ ("ebraille/vol0.html#page_1", "i", "⠊"),
+ ("ebraille/vol0.html#page_2", "1", "⠼⠁"),
+ ]
diff --git a/gui/Convert2EBRL.pyw b/gui/Convert2EBRL.pyw
index d3be1b7..d29e6de 100644
--- a/gui/Convert2EBRL.pyw
+++ b/gui/Convert2EBRL.pyw
@@ -11,6 +11,8 @@
# nuitka-project: --enable-plugins=pyside6
# nuitka-project: --include-package-data=brf2ebrl
# nuitka-project: --include-package=brf2ebrl_bana
+# nuitka-project: --include-package-data=louis
+# nuitka-project: --include-data-files={MAIN_DIRECTORY}/../vendor/liblouis/src/louis/liblouis.dll=louis/liblouis.dll
# nuitka-project: --product-version={APP_VERSION}
import sys
diff --git a/liblouis_changed.md b/liblouis_changed.md
new file mode 100644
index 0000000..891d5e4
--- /dev/null
+++ b/liblouis_changed.md
@@ -0,0 +1,76 @@
+# liblouis integration: page list titles
+
+## Why
+
+eBraille 1.0, section 8.3.2 (Page list):
+
+> Each entry in the page list MUST include the print page number equivalent in a title attribute.
+
+The spec's example puts the `title` on the `` inside each ``:
+
+```html
+⠼⠁
+```
+
+Before this change, `index.html` page list entries had no `title`. `PageRef.title` existed but was always set to `""` and never written out.
+
+## What changed
+
+### New: `vendor/liblouis` workspace package (distribution `liblouis`, import `louis`)
+
+liblouis does not publish its Python bindings to PyPI. The `louis` and `pylouis` projects on PyPI are unrelated to liblouis and must not be used. Everything here comes from liblouis v3.39.0:
+
+| File | Source |
+| --- | --- |
+| `src/louis/__init__.py` | Official ctypes bindings (`python/louis/__init__.py.in`). The only change is the library loading, marked with a `Convert2EBRL` comment: it loads `liblouis.dll` from the package directory on Windows and a system liblouis elsewhere. |
+| `src/louis/liblouis.dll` | `bin/` of `liblouis-3.39.0-win64.zip`. The sha256 `64d669ac…fbc6591` matches the GitHub release asset digest. It only depends on `KERNEL32.dll` and `msvcrt.dll`. |
+| `src/louis/tables/` | `unicode.dis`, `en-ueb-g1.ctb` and the 7 tables they include (about 95 KB, not the full 15 MB table set). |
+| `src/louis/bundled.py` | New helper: `table_path(name)` returns the absolute path to a bundled table. |
+| `COPYING.LESSER` | liblouis license (LGPL-2.1-or-later). |
+| `README.md` | Provenance and update steps. |
+
+Tables are passed to liblouis as absolute paths. Setting `LOUIS_TABLEPATH` from Python does not reach the DLL, because it keeps a separate `msvcrt` environment, and `lou_setDataPath` is deprecated.
+
+### `brf2ebrl`
+
+- `pyproject.toml`: depends on `liblouis`, with `[tool.uv.sources] liblouis = { workspace = true }`.
+- New `src/brf2ebrl/utils/back_translation.py`: `back_translate_page_number(braille) -> str`. It back-translates with `unicode.dis` + `en-ueb-g1.ctb` and caches results. It uses grade 1 because page numbers are uncontracted, and grade 2 would turn roman numerals into words (`⠭` → "it", `⠇` → "like"). It logs a warning if liblouis returns untranslatable markers.
+- `src/brf2ebrl/plugin.py`: `EBrlZippedBundler._create_navigation_html` fills `PageRef.title` with the back-translated page number.
+- `src/brf2ebrl/utils/ebrl.py`: page list links are written as ``.
+- New `tests/test_back_translation.py`: tests page number back-translation (arabic, roman, `W1`-style prefixes, continuation `a2`, ranges `1-2`) and checks that the nav page list outputs `title`.
+
+### Workspace and GUI
+
+- Root `pyproject.toml`: adds `vendor/liblouis` to the workspace members.
+- `uv.lock`: adds the `liblouis` entry.
+- `gui/Convert2EBRL.pyw`: new Nuitka options. `--include-package-data` copies the tables but never DLLs, so the DLL needs its own option:
+ ```
+ # nuitka-project: --include-package-data=louis
+ # nuitka-project: --include-data-files={MAIN_DIRECTORY}/../vendor/liblouis/src/louis/liblouis.dll=louis/liblouis.dll
+ ```
+- Root `README.md`: lists the `vendor/liblouis` subproject.
+- `.github/workflows/python-app.yml`: the "Collect files for artifact" step copies liblouis's `COPYING.LESSER` to `Convert2EBRL.dist\louis\` in the artifact and release zip, as the LGPL requires.
+
+## Result
+
+```html
+⠠⠺⠼⠁
+⠼⠁⠤⠼⠃
+⠁⠼⠃
+```
+
+## Verification
+
+- `uv run pytest` in `brf2ebrl`: 137 passed, 4 failed. The 4 failures are in `test_block_detectors.py` and also fail without these changes.
+- CLI conversion of `A-B2517-V01.BRF` and `A-B2517-V02.BRF`: all 54 page list entries have a `title`, and none have untranslatable markers.
+- Minimal Nuitka standalone build using the options above: the exe loads the bundled DLL and tables and back-translates correctly.
+- Full GUI Nuitka build (`gui\Convert2EBRL.pyw`, same command as CI): succeeds, and `Convert2EBRL.dist/louis/` contains `liblouis.dll` and all 9 tables.
+
+## Status
+
+Committed on branch `liblouis-page-list-titles`, not yet pushed. The files touched are exactly those listed under "What changed" plus this file.
+
+## Follow-ups
+
+- Other braille codes (non-UEB plugins) will need their own tables. The table choice is currently fixed to UEB grade 1 in `back_translation.py`.
+- The same mechanism can fill the nav `
` and `dc:title`, which are currently `"-"`. That needs `en-ueb-g2.ctb` added to the bundled tables.
diff --git a/pyproject.toml b/pyproject.toml
index 81c620e..54bd557 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -10,4 +10,5 @@ members = [
"gui",
"brf2ebrl",
"plugins/brf2ebrl_bana",
+ "vendor/liblouis",
]
diff --git a/uv.lock b/uv.lock
index 4882b72..4076db0 100644
--- a/uv.lock
+++ b/uv.lock
@@ -8,6 +8,7 @@ members = [
"brf2ebrl-bana",
"convert2ebrl",
"convert2ebrl-workspace",
+ "liblouis",
]
[[package]]
@@ -16,6 +17,7 @@ version = "0.1.0"
source = { editable = "brf2ebrl" }
dependencies = [
{ name = "html5lib" },
+ { name = "liblouis" },
{ name = "lxml" },
{ name = "pdfplumber" },
{ name = "pypdf" },
@@ -30,6 +32,7 @@ dev = [
[package.metadata]
requires-dist = [
{ name = "html5lib", specifier = ">=1.1" },
+ { name = "liblouis", editable = "vendor/liblouis" },
{ name = "lxml", specifier = ">=6.1.0" },
{ name = "pdfplumber", specifier = ">=0.11.10" },
{ name = "pypdf", specifier = ">=6.13.3" },
@@ -197,6 +200,11 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
]
+[[package]]
+name = "liblouis"
+version = "3.39.0"
+source = { editable = "vendor/liblouis" }
+
[[package]]
name = "lxml"
version = "6.1.1"
diff --git a/vendor/liblouis/COPYING.LESSER b/vendor/liblouis/COPYING.LESSER
new file mode 100644
index 0000000..4362b49
--- /dev/null
+++ b/vendor/liblouis/COPYING.LESSER
@@ -0,0 +1,502 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ , 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/vendor/liblouis/README.md b/vendor/liblouis/README.md
new file mode 100644
index 0000000..e0cf6a0
--- /dev/null
+++ b/vendor/liblouis/README.md
@@ -0,0 +1,23 @@
+# liblouis (vendored)
+
+A vendored copy of [liblouis](https://liblouis.io/) used by brf2ebrl to back-translate braille (for example page numbers in the eBraille page list). It is packaged here because liblouis does not publish its Python bindings to PyPI; the `louis` and `pylouis` projects on PyPI are not liblouis and must not be used.
+
+Liblouis is licensed under the LGPL 2.1 or later, see [COPYING.LESSER](COPYING.LESSER).
+
+## Contents
+
+All files come from liblouis v3.39.0.
+
+* `src/louis/__init__.py`: the official ctypes bindings (`python/louis/__init__.py.in` in the source tree). The only change is the library loading, marked with a `Convert2EBRL` comment.
+* `src/louis/liblouis.dll`: from `bin/` in `liblouis-3.39.0-win64.zip` (sha256 `64d669ac30f1411e0023b1cecc81c7a7b5374678ee41302c95ac8c7c8fbc6591`, matching the GitHub release asset digest). It only depends on `KERNEL32.dll` and `msvcrt.dll`.
+* `src/louis/tables/`: `unicode.dis`, `en-ueb-g1.ctb` and the tables they include, from `share/liblouis/tables/` in the same zip.
+* `src/louis/bundled.py`: helper giving absolute paths to the bundled tables.
+
+On platforms other than Windows the bindings load a system installed liblouis, but still use the bundled tables.
+
+## Updating
+
+1. Download `liblouis--win64.zip` from the [liblouis releases](https://github.com/liblouis/liblouis/releases) and check its sha256 against the release asset digest.
+2. Replace `liblouis.dll` and the files in `tables/` (add any newly included tables).
+3. Replace `__init__.py` with `python/louis/__init__.py.in` from the matching tag and reapply the library loading change.
+4. Update the version in `pyproject.toml` and this README, then run `uv lock`.
diff --git a/vendor/liblouis/pyproject.toml b/vendor/liblouis/pyproject.toml
new file mode 100644
index 0000000..34fe9cd
--- /dev/null
+++ b/vendor/liblouis/pyproject.toml
@@ -0,0 +1,15 @@
+[project]
+name = "liblouis"
+version = "3.39.0"
+description = "Vendored liblouis Python bindings, Windows DLL and the tables used by brf2ebrl."
+readme = "README.md"
+requires-python = ">=3.12"
+license = {text = "LGPL-2.1-or-later"}
+dependencies = []
+
+[tool.uv.build-backend]
+module-name = "louis"
+
+[build-system]
+requires = ["uv_build>=0.11.3,<0.12.0"]
+build-backend = "uv_build"
diff --git a/vendor/liblouis/src/louis/__init__.py b/vendor/liblouis/src/louis/__init__.py
new file mode 100644
index 0000000..96be6db
--- /dev/null
+++ b/vendor/liblouis/src/louis/__init__.py
@@ -0,0 +1,779 @@
+# Liblouis Python ctypes bindings
+#
+# Copyright (C) 2009-2010 James Teh
+# Copyright (C) 2010-2012 Michael Whapples
+# Copyright (C) 2012-2024 Christian Egli
+# Copyright (C) 2015-2016 Davy Kager
+# Copyright (C) 2016 matt venn
+# Copyright (C) 2018-2025 Leonard de Ruijter
+# Copyright (C) 2018 Bue Vester-Andersen
+# Copyright (C) 2019 Dave Mielke
+# Copyright (C) 2019-2020 André-Abush Clause
+# Copyright (C) 2019 Bert Frees
+# Copyright (C) 2023 Rob Beezer
+# Copyright (C) 2024 Daniel Garcia Moreno
+#
+# This file is part of liblouis.
+#
+# liblouis is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# liblouis is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with liblouis. If not, see .
+#
+
+"""Liblouis Python ctypes bindings
+These bindings allow you to use the liblouis braille translator and back-translator library
+from within Python.
+This documentation is only related to the Python helper.
+Please see the liblouis documentation for more information.
+
+Most of these functions take a C{tableList} argument which specifies
+a list of translation tables to use. Please see the liblouis documentation
+concerning the C{tableList} parameter to the C{lou_translateString}
+function for information about how liblouis searches for these tables.
+
+:author: Michael Curran
+:author: James Teh
+:author: Eitan Isaacson
+:author: Michael Whapples
+:author: Davy Kager
+:author: Leonard de Ruijter
+:author: Babbage B.V.
+:author: Andre-Abush Clause
+"""
+
+from atexit import register
+from collections.abc import Generator, Iterable, Sequence
+from ctypes import (
+ Array,
+ CFUNCTYPE,
+ POINTER,
+ c_char,
+ c_char_p,
+ c_int,
+ c_ushort,
+ cdll,
+ create_string_buffer,
+ string_at,
+)
+from sys import (
+ byteorder,
+ getdefaultencoding,
+ getfilesystemencoding,
+ platform,
+)
+
+try: # Native win32
+ from ctypes import WINFUNCTYPE, windll
+
+ _loader, _functype = windll, WINFUNCTYPE
+except ImportError: # Unix/Cygwin
+ _loader, _functype = cdll, CFUNCTYPE
+# Convert2EBRL: load the liblouis.dll bundled next to this file on Windows and
+# fall back to a system liblouis elsewhere, rather than a configure-time SONAME.
+_is_windows = platform == "win32"
+if _is_windows:
+ from os.path import dirname, join
+
+ liblouis = _loader[join(dirname(__file__), "liblouis.dll")]
+else:
+ from ctypes.util import find_library
+
+ liblouis = _loader[find_library("louis") or "liblouis.so.20"]
+_endianness = "be" if byteorder == "big" else "le"
+
+# { Module Configuration
+wideCharBytes: int = liblouis.lou_charSize()
+"""
+Specifies the charSize (in bytes) used by liblouis.
+This is fetched once using `liblouis.lou_charSize`.
+Call it directly, since `charSize` is not yet defined.
+"""
+outlenMultiplier: int = 4 + wideCharBytes * 2
+"""
+Specifies the number by which the input length should be multiplied
+to calculate the maximum output length.
+The default will handle the case where every input character is
+undefined in the translation table.
+"""
+fileSystemEncoding: str = "mbcs" if _is_windows else getfilesystemencoding()
+"""Specifies the encoding to use when encode/decode file/dir name."""
+conversionEncoding: str = "utf_%d_%s" % (wideCharBytes * 8, _endianness)
+"""Specifies the encoding to use when converting from byte strings to unicode strings."""
+
+
+# Some general utility functions
+TableListT = list[str | bytes]
+
+
+def _createTableBuf(tablesList: TableListT) -> Array[c_char]:
+ """Creates a tables string for liblouis calls"""
+ return create_string_buffer(
+ b",".join(
+ [
+ x.encode(fileSystemEncoding) if isinstance(x, str) else bytes(x)
+ for x in tablesList
+ ]
+ )
+ )
+
+
+def _createTypeformbuf(
+ length: int,
+ typeform: Iterable[int] | None = None,
+) -> Array[c_ushort]:
+ """Creates a typeform buffer for liblouis calls"""
+ return (c_ushort * length)(*typeform) if typeform else (c_ushort * length)()
+
+
+ENCODING_ERROR_HANDLER = "surrogatepass"
+
+
+def _createEncodedBuf(
+ x: str,
+ encoding: str = conversionEncoding,
+ errors: str = ENCODING_ERROR_HANDLER,
+) -> Array[c_char]:
+ return create_string_buffer(x.encode(encoding, errors))
+
+
+def _processTableFiles(stringArray: Sequence[bytes] | None) -> Generator[str]:
+ if not stringArray:
+ return
+ i = 0
+ while stringArray[i] is not None:
+ yield stringArray[i].decode(fileSystemEncoding, errors=ENCODING_ERROR_HANDLER)
+ i += 1
+ liblouis.lou_freeTableFiles(stringArray)
+
+
+def _createQueryStringBuf(dct: dict[str, str]) -> Array[c_char]:
+ """Create a query string from a dictionary"""
+ if not isinstance(dct, dict):
+ raise TypeError("Query should be a dictionary")
+ return create_string_buffer(
+ " ".join(
+ f"{k}:{v}"
+ for k, v in dct.items()
+ if isinstance(k, str) and isinstance(v, str)
+ ).encode(getdefaultencoding(), errors=ENCODING_ERROR_HANDLER)
+ )
+
+
+register(liblouis.lou_free)
+
+liblouis.lou_version.restype = c_char_p
+liblouis.lou_version.argtypes = ()
+
+liblouis.lou_charSize.restype = c_int
+liblouis.lou_charSize.argtypes = ()
+
+liblouis.lou_translateString.restype = c_int
+liblouis.lou_translateString.argtypes = (
+ c_char_p,
+ POINTER(c_char),
+ POINTER(c_int),
+ POINTER(c_char),
+ POINTER(c_int),
+ POINTER(c_ushort),
+ POINTER(c_char),
+ c_int,
+)
+
+liblouis.lou_translate.restype = c_int
+liblouis.lou_translate.argtypes = (
+ c_char_p,
+ POINTER(c_char),
+ POINTER(c_int),
+ POINTER(c_char),
+ POINTER(c_int),
+ POINTER(c_ushort),
+ POINTER(c_char),
+ POINTER(c_int),
+ POINTER(c_int),
+ POINTER(c_int),
+ c_int,
+)
+
+liblouis.lou_backTranslateString.restype = c_int
+liblouis.lou_backTranslateString.argtypes = (
+ c_char_p,
+ POINTER(c_char),
+ POINTER(c_int),
+ POINTER(c_char),
+ POINTER(c_int),
+ POINTER(c_ushort),
+ POINTER(c_char),
+ c_int,
+)
+
+liblouis.lou_backTranslate.restype = c_int
+liblouis.lou_backTranslate.argtypes = (
+ c_char_p,
+ POINTER(c_char),
+ POINTER(c_int),
+ POINTER(c_char),
+ POINTER(c_int),
+ POINTER(c_ushort),
+ POINTER(c_char),
+ POINTER(c_int),
+ POINTER(c_int),
+ POINTER(c_int),
+ c_int,
+)
+
+liblouis.lou_hyphenate.restype = c_int
+liblouis.lou_hyphenate.argtypes = (
+ c_char_p,
+ POINTER(c_char),
+ c_int,
+ POINTER(c_char),
+ c_int,
+)
+
+liblouis.lou_checkTable.restype = c_int
+liblouis.lou_checkTable.argtypes = (c_char_p,)
+
+liblouis.lou_compileString.restype = c_int
+liblouis.lou_compileString.argtypes = (c_char_p, c_char_p)
+
+liblouis.lou_getTypeformForEmphClass.restype = c_ushort
+liblouis.lou_getTypeformForEmphClass.argtypes = (c_char_p, c_char_p)
+
+liblouis.lou_dotsToChar.restype = c_int
+liblouis.lou_dotsToChar.argtypes = (
+ c_char_p,
+ POINTER(c_char),
+ POINTER(c_char),
+ c_int,
+ c_int,
+)
+
+liblouis.lou_charToDots.restype = c_int
+liblouis.lou_charToDots.argtypes = (
+ c_char_p,
+ POINTER(c_char),
+ POINTER(c_char),
+ c_int,
+ c_int,
+)
+
+LogCallback = _functype(None, c_int, c_char_p)
+
+liblouis.lou_registerLogCallback.restype = None
+liblouis.lou_registerLogCallback.argtypes = (LogCallback,)
+
+liblouis.lou_setLogLevel.restype = None
+liblouis.lou_setLogLevel.argtypes = (c_int,)
+
+liblouis.lou_findTable.restype = POINTER(c_char)
+liblouis.lou_findTable.argtypes = (c_char_p,)
+
+liblouis.lou_freeTableFile.restype = None
+liblouis.lou_freeTableFile.argtypes = (POINTER(c_char),)
+
+liblouis.lou_findTables.restype = POINTER(c_char_p)
+liblouis.lou_findTables.argtypes = (c_char_p,)
+
+liblouis.lou_freeTableFiles.restype = None
+liblouis.lou_freeTableFiles.argtypes = (POINTER(c_char_p),)
+
+liblouis.lou_getTableInfo.restype = POINTER(c_char)
+liblouis.lou_getTableInfo.argtypes = (c_char_p, c_char_p)
+
+liblouis.lou_freeTableInfo.restype = None
+liblouis.lou_freeTableInfo.argtypes = (liblouis.lou_getTableInfo.restype,)
+
+liblouis.lou_listTables.restype = POINTER(c_char_p)
+liblouis.lou_listTables.argtypes = ()
+
+liblouis.lou_free.restype = None
+liblouis.lou_free.argtypes = ()
+
+
+def version() -> str:
+ """Obtain version information for liblouis.
+ :return: The version of liblouis, plus other information, such as
+ the release date and perhaps notable changes.
+ """
+ return liblouis.lou_version().decode("ASCII")
+
+
+def charSize() -> int:
+ """Obtain charSize information for liblouis.
+ :return: The size of the widechar with which liblouis was compiled.
+ """
+ return liblouis.lou_charSize()
+
+
+def translate(
+ tableList: TableListT,
+ inbuf: str,
+ typeform: list[int] | None = None,
+ cursorPos: int = 0,
+ mode: int = 0,
+) -> tuple[str, list[int], list[int], int]:
+ """Translate a string of characters, providing position information.
+ :param tableList: A list of translation tables.
+ :param inbuf: The string to translate.
+ :param typeform: A list of typeform constants indicating the typeform for each position in inbuf,
+ `None` for no typeform information.
+ :param cursorPos: The position of the cursor in inbuf.
+ :param mode: The translation mode; add multiple values for a combined mode.
+ :return: A tuple of: the translated string,
+ a list of input positions for each position in the output,
+ a list of output positions for each position in the input, and
+ the position of the cursor in the output.
+ :raise RuntimeError: If a complete translation could not be done.
+ :see: lou_translate in the liblouis documentation
+ """
+ tableBuf: Array[c_char] = _createTableBuf(tableList)
+ _inbuf = _createEncodedBuf(inbuf)
+ inlen = c_int(len(_inbuf) // wideCharBytes)
+ outlen = c_int(inlen.value * outlenMultiplier)
+ outbuf = create_string_buffer(outlen.value * wideCharBytes)
+ typeformbuf = None
+ if typeform:
+ typeformbuf = _createTypeformbuf(outlen.value, typeform)
+ inPos = (c_int * outlen.value)()
+ outPos = (c_int * inlen.value)()
+ _cursorPos = c_int(cursorPos)
+ if not liblouis.lou_translate(
+ tableBuf,
+ _inbuf,
+ inlen,
+ outbuf,
+ outlen,
+ typeformbuf,
+ None,
+ outPos,
+ inPos,
+ _cursorPos,
+ mode,
+ ):
+ raise RuntimeError(
+ f"Can't translate: tables {tableList!r}, inbuf {inbuf!r}, typeform {typeform!r}, cursorPos {cursorPos!r}, mode {mode!r}"
+ )
+ if isinstance(typeform, list) and typeformbuf is not None:
+ typeform[:] = list(typeformbuf)
+ return (
+ outbuf.raw[: outlen.value * wideCharBytes].decode(
+ conversionEncoding,
+ errors=ENCODING_ERROR_HANDLER,
+ ),
+ inPos[: outlen.value],
+ outPos[: inlen.value],
+ _cursorPos.value,
+ )
+
+
+def translateString(
+ tableList: TableListT,
+ inbuf: str,
+ typeform: list[int] | None = None,
+ mode: int = 0,
+) -> str:
+ """Translate a string of characters.
+ :param tableList: A list of translation tables.
+ :param inbuf: The string to translate.
+ :param typeform: A list of typeform constants indicating the typeform for each position in inbuf,
+ `None` for no typeform information.
+ :param mode: The translation mode; add multiple values for a combined mode.
+ :return: The translated string.
+ :raise RuntimeError: If a complete translation could not be done.
+ :see: lou_translateString in the liblouis documentation
+ """
+ tableBuf = _createTableBuf(tableList)
+ _inbuf = _createEncodedBuf(inbuf)
+ inlen = c_int(len(_inbuf) // wideCharBytes)
+ outlen = c_int(inlen.value * outlenMultiplier)
+ outbuf = create_string_buffer(outlen.value * wideCharBytes)
+ typeformbuf = None
+ if typeform:
+ typeformbuf = _createTypeformbuf(outlen.value, typeform)
+ if not liblouis.lou_translateString(
+ tableBuf,
+ _inbuf,
+ inlen,
+ outbuf,
+ outlen,
+ typeformbuf,
+ None,
+ mode,
+ ):
+ raise RuntimeError(
+ f"Can't translate: tables {tableList}, inbuf {inbuf}, typeform {typeform}, mode {mode}"
+ )
+ if isinstance(typeform, list) and typeformbuf is not None:
+ typeform[:] = list(typeformbuf)
+ return outbuf.raw[: outlen.value * wideCharBytes].decode(
+ conversionEncoding,
+ errors=ENCODING_ERROR_HANDLER,
+ )
+
+
+def backTranslate(
+ tableList: TableListT,
+ inbuf: str,
+ typeform: list[int] | None = None,
+ cursorPos: int = 0,
+ mode: int = 0,
+) -> tuple[str, list[int], list[int], int]:
+ """Back translates a string of characters, providing position information.
+ :param tableList: A list of translation tables.
+ :param inbuf: Braille to back translate.
+ :param typeform: List where typeform constants will be placed.
+ :param cursorPos: Position of cursor.
+ :param mode: Translation mode.
+ :return: A tuple: A string of the back translation,
+ a list of input positions for each position in the output,
+ a list of the output positions for each position in the input and
+ the position of the cursor in the output.
+ :raise RuntimeError: If a complete back translation could not be done.
+ :see: lou_backTranslate in the liblouis documentation.
+ """
+ tableBuf = _createTableBuf(tableList)
+ _inbuf = _createEncodedBuf(inbuf)
+ inlen = c_int(len(_inbuf) // wideCharBytes)
+ outlen = c_int(inlen.value * outlenMultiplier)
+ outbuf = create_string_buffer(outlen.value * wideCharBytes)
+ typeformbuf = None
+ if isinstance(typeform, list):
+ typeformbuf = _createTypeformbuf(outlen.value)
+ inPos = (c_int * outlen.value)()
+ outPos = (c_int * inlen.value)()
+ _cursorPos = c_int(cursorPos)
+ if not liblouis.lou_backTranslate(
+ tableBuf,
+ _inbuf,
+ inlen,
+ outbuf,
+ outlen,
+ typeformbuf,
+ None,
+ outPos,
+ inPos,
+ _cursorPos,
+ mode,
+ ):
+ raise RuntimeError(
+ f"Can't back translate: tables {tableList!r}, inbuf {inbuf!r}, typeform {typeform!r}, cursorPos {cursorPos!r}, mode {mode!r}"
+ )
+ if isinstance(typeform, list) and typeformbuf is not None:
+ typeform[:] = list(typeformbuf)
+ return (
+ outbuf.raw[: outlen.value * wideCharBytes].decode(
+ conversionEncoding,
+ errors=ENCODING_ERROR_HANDLER,
+ ),
+ inPos[: outlen.value],
+ outPos[: inlen.value],
+ _cursorPos.value,
+ )
+
+
+def backTranslateString(
+ tableList: TableListT,
+ inbuf: str,
+ typeform: list[int] | None = None,
+ mode: int = 0,
+) -> str:
+ """Back translate from Braille.
+ :param tableList: A list of translation tables.
+ :param inbuf: The Braille to back translate.
+ :param typeform: List for typeform constants to be put in.
+ If you don't want typeform data then give `None`
+ :param mode: The translation mode
+ :return: The back translation of inbuf.
+ :raise RuntimeError: If a complete back translation could not be done.
+ :see: lou_backTranslateString in the liblouis documentation.
+ """
+ tableBuf = _createTableBuf(tableList)
+ _inbuf = _createEncodedBuf(inbuf)
+ inlen = c_int(len(_inbuf) // wideCharBytes)
+ outlen = c_int(inlen.value * outlenMultiplier)
+ outbuf = create_string_buffer(outlen.value * wideCharBytes)
+ typeformbuf = None
+ if isinstance(typeform, list):
+ typeformbuf = _createTypeformbuf(outlen.value)
+ if not liblouis.lou_backTranslateString(
+ tableBuf,
+ _inbuf,
+ inlen,
+ outbuf,
+ outlen,
+ typeformbuf,
+ None,
+ mode,
+ ):
+ raise RuntimeError(
+ f"Can't back translate: tables {tableList!r}, inbuf {inbuf!r}, mode {mode!r}"
+ )
+ if isinstance(typeform, list) and typeformbuf is not None:
+ typeform[:] = list(typeformbuf)
+ return outbuf.raw[: outlen.value * wideCharBytes].decode(
+ conversionEncoding,
+ errors=ENCODING_ERROR_HANDLER,
+ )
+
+
+def hyphenate(tableList: TableListT, inbuf: str, mode: int = 0) -> str:
+ """Get information for hyphenation.
+ :param tableList: A list of translation tables and hyphenation
+ dictionaries.
+ :param inbuf: The text to get hyphenation information about.
+ This should be a single word and leading/trailing whitespace
+ and punctuation is ignored.
+ :param mode: Lets liblouis know if inbuf is plain text or Braille.
+ Set to 0 for text and anyother value for Braille.
+ :return: A string with '1' at the beginning of every syllable
+ and '0' elsewhere.
+ :raise RuntimeError: If hyphenation data could not be produced.
+ :see: lou_hyphenate in the liblouis documentation.
+ """
+ tableBuf = _createTableBuf(tableList)
+ _inbuf = _createEncodedBuf(inbuf)
+ inlen = c_int(len(_inbuf) // wideCharBytes)
+ hyphen_string = create_string_buffer(inlen.value + 1)
+ if not liblouis.lou_hyphenate(
+ tableBuf,
+ _inbuf,
+ inlen,
+ hyphen_string,
+ mode,
+ ):
+ raise RuntimeError(
+ f"Can't hyphenate: tables {tableList!r}, inbuf {inbuf!r}, mode {mode!r}"
+ )
+ return hyphen_string.value.decode("ASCII")
+
+
+def checkTable(tableList: TableListT) -> None:
+ """Check if the specified tables can be found and compiled.
+ This can be used to check if a list of tables contains errors
+ before sending it to other liblouis functions
+ that accept a list of tables.
+ :param tableList: A list of translation tables.
+ :raise RuntimeError: If compilation failed.
+ :see: lou_checkTable in the liblouis documentation
+ """
+ tableBuf = _createTableBuf(tableList)
+ if not liblouis.lou_checkTable(tableBuf):
+ raise RuntimeError(f"Can't compile: tables {tableList}")
+
+
+def compileString(tableList: TableListT, inString: str) -> None:
+ """Compile a table entry on the fly at run-time.
+ :param tableList: A list of translation tables.
+ :param inString: The table entry to be added.
+ :raise RuntimeError: If compilation of the entry failed.
+ :see: lou_compileString in the liblouis documentation
+ """
+ tableBuf = _createTableBuf(tableList)
+ inbuf = create_string_buffer(
+ inString.encode("ASCII") if isinstance(inString, str) else bytes(inString)
+ )
+ if not liblouis.lou_compileString(tableBuf, inbuf):
+ raise RuntimeError(
+ f"Can't compile entry: tables {tableList}, inString {inString}"
+ )
+
+
+def getTypeformForEmphClass(tableList: TableListT, emphClass: str) -> int:
+ """Get the typeform bit for the named emphasis class.
+ :param tableList: A list of translation tables.
+ :param emphClass: An emphasis class name.
+ :see: lou_getTypeformForEmphClass in the liblouis documentation
+ """
+ tableBuf = _createTableBuf(tableList)
+ bEmphClass = emphClass.encode("ASCII")
+ return liblouis.lou_getTypeformForEmphClass(tableBuf, bEmphClass)
+
+
+def dotsToChar(tableList: TableListT, inbuf: str) -> str:
+ """Convert a string of dot patterns to a string of characters according to the specifications in tableList.
+ :param tableList: A list of translation tables.
+ :param inbuf: a string of dot patterns, either in liblouis format or Unicode braille.
+ :raise RuntimeError: If a complete conversion could not be done.
+ :see: lou_dotsToChar in the liblouis documentation
+ """
+ tableBuf = _createTableBuf(tableList)
+ _inbuf = _createEncodedBuf(inbuf)
+ length = c_int(len(inbuf) // wideCharBytes)
+ outbuf = create_string_buffer(length.value * wideCharBytes)
+ if not liblouis.lou_dotsToChar(tableBuf, _inbuf, outbuf, length, 0):
+ raise RuntimeError(
+ f"Can't convert dots to char: tables {tableList}, inbuf {inbuf!r}"
+ )
+ return outbuf.raw[: length.value * wideCharBytes].decode(
+ conversionEncoding,
+ errors=ENCODING_ERROR_HANDLER,
+ )
+
+
+def charToDots(tableList: TableListT, inbuf: str, mode: int = 0) -> str:
+ """Convert a string of characterss to a string of dot patterns according to the specifications in tableList.
+ :param tableList: A list of translation tables.
+ :param inbuf: a string of characters.
+ :param mode: The translation mode; add multiple values for a combined mode.
+ :raise RuntimeError: If a complete conversion could not be done.
+ :see: lou_charToDots in the liblouis documentation
+ """
+ tableBuf = _createTableBuf(tableList)
+ _inbuf = _createEncodedBuf(inbuf)
+ length = c_int(len(inbuf) // wideCharBytes)
+ outbuf = create_string_buffer(length.value * wideCharBytes)
+ if not liblouis.lou_charToDots(tableBuf, _inbuf, outbuf, length, mode):
+ raise RuntimeError(
+ f"Can't convert char to dots: tables {tableList!r}, inbuf {inbuf!r}, mode {mode!r}"
+ )
+ return outbuf.raw[: length.value * wideCharBytes].decode(
+ conversionEncoding,
+ errors=ENCODING_ERROR_HANDLER,
+ )
+
+
+def registerLogCallback(logCallback) -> None:
+ """Register logging callbacks.
+ Set to `None` for default callback.
+ :param logCallback: The callback to use.
+ The callback must take two arguments:
+ :param level: The log level on which a message is logged.
+ :type level: int
+ :param message: The logged message.
+ Note that the callback should provide its own UTF-8 decoding routine.
+ :type message: bytes
+
+ Example callback:
+
+ @louis.LogCallback
+ def incomingLouisLog(level, message):
+ print("Message %s logged at level %d" % (message.decode("ASCII"), level))
+
+ @type logCallback: `LogCallback`
+ """
+ if logCallback is None:
+ logCallback = LogCallback(0)
+ elif not isinstance(logCallback, LogCallback):
+ raise TypeError(
+ f"logCallback should be of type {LogCallback.__name__} or NoneType"
+ )
+ return liblouis.lou_registerLogCallback(logCallback)
+
+
+def setLogLevel(level: int) -> None:
+ """Set the level for logging callback to be called at.
+ :param level: one of the C{LOG_*} constants.
+ :raise ValueError: If an invalid log level is provided.
+ """
+ if level not in logLevels:
+ raise ValueError("Level %d is an invalid log level" % level)
+ return liblouis.lou_setLogLevel(level)
+
+
+def findTable(query: dict[str, str]) -> str | None:
+ """Find the best match for a query
+
+ Returns the name of the table, or None when no match can be
+ found. An error message is given when the query is invalid. Freeing.
+ :param query: The query to lookup.
+ """
+ queryStr = _createQueryStringBuf(query)
+ result = liblouis.lou_findTable(queryStr)
+ if not result:
+ return None
+ string = string_at(result).decode(fileSystemEncoding, errors=ENCODING_ERROR_HANDLER)
+ liblouis.lou_freeTableFile(result)
+ return string
+
+
+def findTables(query: dict[str, str]) -> list[str]:
+ """Find all matches for a query, best match first.
+
+ Returns the names of the matched tables.
+ An error message is given when the query is invalid.
+ :param query: The query to lookup.
+ """
+ queryStr = _createQueryStringBuf(query)
+ result = liblouis.lou_findTables(queryStr)
+ return list(_processTableFiles(result))
+
+
+def getTableInfo(tableName: str, key: str) -> str | None:
+ """Read metadata from a file.
+
+ Returns the value of the first occurring metadata field specified by
+ `key' in `table', or None when the field does not exist.
+ """
+ bTableName = _createEncodedBuf(tableName, fileSystemEncoding)
+ bKey = _createEncodedBuf(key, getdefaultencoding())
+ result = liblouis.lou_getTableInfo(bTableName, bKey)
+ if not result:
+ return None
+ string = string_at(result).decode(errors=ENCODING_ERROR_HANDLER)
+ liblouis.lou_freeTableInfo(result)
+ return string
+
+
+def listTables() -> list[str]:
+ """List available tables.
+
+ Returns the names of available tables as list of strings.
+ Only tables that are discoverable, i.e. the have active metadata, are listed.
+ """
+ result = liblouis.lou_listTables()
+ return list(_processTableFiles(result))
+
+
+# { Typeforms
+plain_text = 0x0000
+emph_1 = comp_emph_1 = italic = 0x0001
+emph_2 = comp_emph_2 = underline = 0x0002
+emph_3 = comp_emph_3 = bold = 0x0004
+emph_4 = 0x0008
+emph_5 = 0x0010
+emph_6 = 0x0020
+emph_7 = 0x0040
+emph_8 = 0x0080
+emph_9 = 0x0100
+emph_10 = 0x0200
+computer_braille = 0x0400
+no_translate = 0x0800
+no_contract = 0x1000
+# }
+
+# { Translation modes
+noContractions = 1
+compbrlAtCursor = 2
+dotsIO = 4
+compbrlLeftCursor = 32
+ucBrl = 64
+noUndefined = 128
+noUndefinedDots = noUndefined # alias for backward compatiblity
+partialTrans = 256
+# }
+
+# { logLevels
+LOG_ALL = 0
+LOG_DEBUG = 10000
+LOG_INFO = 20000
+LOG_WARN = 30000
+LOG_ERROR = 40000
+LOG_FATAL = 50000
+LOG_OFF = 60000
+# }
+
+logLevels = (LOG_ALL, LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL, LOG_OFF)
+
+if __name__ == "__main__":
+ # Just some common tests.
+ print(version())
+ print(translate([b"../tables/en-us-g2.ctb"], "Hello world!", cursorPos=5))
diff --git a/vendor/liblouis/src/louis/bundled.py b/vendor/liblouis/src/louis/bundled.py
new file mode 100644
index 0000000..414bfd7
--- /dev/null
+++ b/vendor/liblouis/src/louis/bundled.py
@@ -0,0 +1,9 @@
+"""Paths to the liblouis tables bundled with this package."""
+from pathlib import Path
+
+TABLES_DIR = Path(__file__).parent / "tables"
+
+
+def table_path(name: str) -> str:
+ """Absolute path of a bundled table, usable in a liblouis table list."""
+ return str(TABLES_DIR / name)
diff --git a/vendor/liblouis/src/louis/liblouis.dll b/vendor/liblouis/src/louis/liblouis.dll
new file mode 100644
index 0000000..bd5df09
Binary files /dev/null and b/vendor/liblouis/src/louis/liblouis.dll differ
diff --git a/vendor/liblouis/src/louis/tables/braille-patterns.cti b/vendor/liblouis/src/louis/tables/braille-patterns.cti
new file mode 100644
index 0000000..1cb7df6
--- /dev/null
+++ b/vendor/liblouis/src/louis/tables/braille-patterns.cti
@@ -0,0 +1,287 @@
+#
+# Copyright (C) 2010, 2011 DocArch .
+#
+# This file is part of liblouis.
+#
+# liblouis is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation, either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# liblouis is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with liblouis. If not, see
+# .
+#
+# ----------------------------------------------------------------------------------------------
+# odt2braille - Braille authoring in OpenOffice.org.
+# ----------------------------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------------------------
+# Unicode 2800..28FF Braille Patterns
+# ----------------------------------------------------------------------------------------------
+
+noback sign \x2800 0 # ⠀ BRAILLE PATTERN DOTS-0
+noback sign \x2801 1 # ⠁ BRAILLE PATTERN DOTS-1
+noback sign \x2802 2 # ⠂ BRAILLE PATTERN DOTS-2
+noback sign \x2803 12 # ⠃ BRAILLE PATTERN DOTS-12
+noback sign \x2804 3 # ⠄ BRAILLE PATTERN DOTS-3
+noback sign \x2805 13 # ⠅ BRAILLE PATTERN DOTS-13
+noback sign \x2806 23 # ⠆ BRAILLE PATTERN DOTS-23
+noback sign \x2807 123 # ⠇ BRAILLE PATTERN DOTS-123
+noback sign \x2808 4 # ⠈ BRAILLE PATTERN DOTS-4
+noback sign \x2809 14 # ⠉ BRAILLE PATTERN DOTS-14
+noback sign \x280A 24 # ⠊ BRAILLE PATTERN DOTS-24
+noback sign \x280B 124 # ⠋ BRAILLE PATTERN DOTS-124
+noback sign \x280C 34 # ⠌ BRAILLE PATTERN DOTS-34
+noback sign \x280D 134 # ⠍ BRAILLE PATTERN DOTS-134
+noback sign \x280E 234 # ⠎ BRAILLE PATTERN DOTS-234
+noback sign \x280F 1234 # ⠏ BRAILLE PATTERN DOTS-1234
+noback sign \x2810 5 # ⠐ BRAILLE PATTERN DOTS-5
+noback sign \x2811 15 # ⠑ BRAILLE PATTERN DOTS-15
+noback sign \x2812 25 # ⠒ BRAILLE PATTERN DOTS-25
+noback sign \x2813 125 # ⠓ BRAILLE PATTERN DOTS-125
+noback sign \x2814 35 # ⠔ BRAILLE PATTERN DOTS-35
+noback sign \x2815 135 # ⠕ BRAILLE PATTERN DOTS-135
+noback sign \x2816 235 # ⠖ BRAILLE PATTERN DOTS-235
+noback sign \x2817 1235 # ⠗ BRAILLE PATTERN DOTS-1235
+noback sign \x2818 45 # ⠘ BRAILLE PATTERN DOTS-45
+noback sign \x2819 145 # ⠙ BRAILLE PATTERN DOTS-145
+noback sign \x281A 245 # ⠚ BRAILLE PATTERN DOTS-245
+noback sign \x281B 1245 # ⠛ BRAILLE PATTERN DOTS-1245
+noback sign \x281C 345 # ⠜ BRAILLE PATTERN DOTS-345
+noback sign \x281D 1345 # ⠝ BRAILLE PATTERN DOTS-1345
+noback sign \x281E 2345 # ⠞ BRAILLE PATTERN DOTS-2345
+noback sign \x281F 12345 # ⠟ BRAILLE PATTERN DOTS-12345
+noback sign \x2820 6 # ⠠ BRAILLE PATTERN DOTS-6
+noback sign \x2821 16 # ⠡ BRAILLE PATTERN DOTS-16
+noback sign \x2822 26 # ⠢ BRAILLE PATTERN DOTS-26
+noback sign \x2823 126 # ⠣ BRAILLE PATTERN DOTS-126
+noback sign \x2824 36 # ⠤ BRAILLE PATTERN DOTS-36
+noback sign \x2825 136 # ⠥ BRAILLE PATTERN DOTS-136
+noback sign \x2826 236 # ⠦ BRAILLE PATTERN DOTS-236
+noback sign \x2827 1236 # ⠧ BRAILLE PATTERN DOTS-1236
+noback sign \x2828 46 # ⠨ BRAILLE PATTERN DOTS-46
+noback sign \x2829 146 # ⠩ BRAILLE PATTERN DOTS-146
+noback sign \x282A 246 # ⠪ BRAILLE PATTERN DOTS-246
+noback sign \x282B 1246 # ⠫ BRAILLE PATTERN DOTS-1246
+noback sign \x282C 346 # ⠬ BRAILLE PATTERN DOTS-346
+noback sign \x282D 1346 # ⠭ BRAILLE PATTERN DOTS-1346
+noback sign \x282E 2346 # ⠮ BRAILLE PATTERN DOTS-2346
+noback sign \x282F 12346 # ⠯ BRAILLE PATTERN DOTS-12346
+noback sign \x2830 56 # ⠰ BRAILLE PATTERN DOTS-56
+noback sign \x2831 156 # ⠱ BRAILLE PATTERN DOTS-156
+noback sign \x2832 256 # ⠲ BRAILLE PATTERN DOTS-256
+noback sign \x2833 1256 # ⠳ BRAILLE PATTERN DOTS-1256
+noback sign \x2834 356 # ⠴ BRAILLE PATTERN DOTS-356
+noback sign \x2835 1356 # ⠵ BRAILLE PATTERN DOTS-1356
+noback sign \x2836 2356 # ⠶ BRAILLE PATTERN DOTS-2356
+noback sign \x2837 12356 # ⠷ BRAILLE PATTERN DOTS-12356
+noback sign \x2838 456 # ⠸ BRAILLE PATTERN DOTS-456
+noback sign \x2839 1456 # ⠹ BRAILLE PATTERN DOTS-1456
+noback sign \x283A 2456 # ⠺ BRAILLE PATTERN DOTS-2456
+noback sign \x283B 12456 # ⠻ BRAILLE PATTERN DOTS-12456
+noback sign \x283C 3456 # ⠼ BRAILLE PATTERN DOTS-3456
+noback sign \x283D 13456 # ⠽ BRAILLE PATTERN DOTS-13456
+noback sign \x283E 23456 # ⠾ BRAILLE PATTERN DOTS-23456
+noback sign \x283F 123456 # ⠿ BRAILLE PATTERN DOTS-123456
+noback sign \x2840 7 # ⡀ BRAILLE PATTERN DOTS-7
+noback sign \x2841 17 # ⡁ BRAILLE PATTERN DOTS-17
+noback sign \x2842 27 # ⡂ BRAILLE PATTERN DOTS-27
+noback sign \x2843 127 # ⡃ BRAILLE PATTERN DOTS-127
+noback sign \x2844 37 # ⡄ BRAILLE PATTERN DOTS-37
+noback sign \x2845 137 # ⡅ BRAILLE PATTERN DOTS-137
+noback sign \x2846 237 # ⡆ BRAILLE PATTERN DOTS-237
+noback sign \x2847 1237 # ⡇ BRAILLE PATTERN DOTS-1237
+noback sign \x2848 47 # ⡈ BRAILLE PATTERN DOTS-47
+noback sign \x2849 147 # ⡉ BRAILLE PATTERN DOTS-147
+noback sign \x284A 247 # ⡊ BRAILLE PATTERN DOTS-247
+noback sign \x284B 1247 # ⡋ BRAILLE PATTERN DOTS-1247
+noback sign \x284C 347 # ⡌ BRAILLE PATTERN DOTS-347
+noback sign \x284D 1347 # ⡍ BRAILLE PATTERN DOTS-1347
+noback sign \x284E 2347 # ⡎ BRAILLE PATTERN DOTS-2347
+noback sign \x284F 12347 # ⡏ BRAILLE PATTERN DOTS-12347
+noback sign \x2850 57 # ⡐ BRAILLE PATTERN DOTS-57
+noback sign \x2851 157 # ⡑ BRAILLE PATTERN DOTS-157
+noback sign \x2852 257 # ⡒ BRAILLE PATTERN DOTS-257
+noback sign \x2853 1257 # ⡓ BRAILLE PATTERN DOTS-1257
+noback sign \x2854 357 # ⡔ BRAILLE PATTERN DOTS-357
+noback sign \x2855 1357 # ⡕ BRAILLE PATTERN DOTS-1357
+noback sign \x2856 2357 # ⡖ BRAILLE PATTERN DOTS-2357
+noback sign \x2857 12357 # ⡗ BRAILLE PATTERN DOTS-12357
+noback sign \x2858 457 # ⡘ BRAILLE PATTERN DOTS-457
+noback sign \x2859 1457 # ⡙ BRAILLE PATTERN DOTS-1457
+noback sign \x285A 2457 # ⡚ BRAILLE PATTERN DOTS-2457
+noback sign \x285B 12457 # ⡛ BRAILLE PATTERN DOTS-12457
+noback sign \x285C 3457 # ⡜ BRAILLE PATTERN DOTS-3457
+noback sign \x285D 13457 # ⡝ BRAILLE PATTERN DOTS-13457
+noback sign \x285E 23457 # ⡞ BRAILLE PATTERN DOTS-23457
+noback sign \x285F 123457 # ⡟ BRAILLE PATTERN DOTS-123457
+noback sign \x2860 67 # ⡠ BRAILLE PATTERN DOTS-67
+noback sign \x2861 167 # ⡡ BRAILLE PATTERN DOTS-167
+noback sign \x2862 267 # ⡢ BRAILLE PATTERN DOTS-267
+noback sign \x2863 1267 # ⡣ BRAILLE PATTERN DOTS-1267
+noback sign \x2864 367 # ⡤ BRAILLE PATTERN DOTS-367
+noback sign \x2865 1367 # ⡥ BRAILLE PATTERN DOTS-1367
+noback sign \x2866 2367 # ⡦ BRAILLE PATTERN DOTS-2367
+noback sign \x2867 12367 # ⡧ BRAILLE PATTERN DOTS-12367
+noback sign \x2868 467 # ⡨ BRAILLE PATTERN DOTS-467
+noback sign \x2869 1467 # ⡩ BRAILLE PATTERN DOTS-1467
+noback sign \x286A 2467 # ⡪ BRAILLE PATTERN DOTS-2467
+noback sign \x286B 12467 # ⡫ BRAILLE PATTERN DOTS-12467
+noback sign \x286C 3467 # ⡬ BRAILLE PATTERN DOTS-3467
+noback sign \x286D 13467 # ⡭ BRAILLE PATTERN DOTS-13467
+noback sign \x286E 23467 # ⡮ BRAILLE PATTERN DOTS-23467
+noback sign \x286F 123467 # ⡯ BRAILLE PATTERN DOTS-123467
+noback sign \x2870 567 # ⡰ BRAILLE PATTERN DOTS-567
+noback sign \x2871 1567 # ⡱ BRAILLE PATTERN DOTS-1567
+noback sign \x2872 2567 # ⡲ BRAILLE PATTERN DOTS-2567
+noback sign \x2873 12567 # ⡳ BRAILLE PATTERN DOTS-12567
+noback sign \x2874 3567 # ⡴ BRAILLE PATTERN DOTS-3567
+noback sign \x2875 13567 # ⡵ BRAILLE PATTERN DOTS-13567
+noback sign \x2876 23567 # ⡶ BRAILLE PATTERN DOTS-23567
+noback sign \x2877 123567 # ⡷ BRAILLE PATTERN DOTS-123567
+noback sign \x2878 4567 # ⡸ BRAILLE PATTERN DOTS-4567
+noback sign \x2879 14567 # ⡹ BRAILLE PATTERN DOTS-14567
+noback sign \x287A 24567 # ⡺ BRAILLE PATTERN DOTS-24567
+noback sign \x287B 124567 # ⡻ BRAILLE PATTERN DOTS-124567
+noback sign \x287C 34567 # ⡼ BRAILLE PATTERN DOTS-34567
+noback sign \x287D 134567 # ⡽ BRAILLE PATTERN DOTS-134567
+noback sign \x287E 234567 # ⡾ BRAILLE PATTERN DOTS-234567
+noback sign \x287F 1234567 # ⡿ BRAILLE PATTERN DOTS-1234567
+noback sign \x2880 8 # ⢀ BRAILLE PATTERN DOTS-8
+noback sign \x2881 18 # ⢁ BRAILLE PATTERN DOTS-18
+noback sign \x2882 28 # ⢂ BRAILLE PATTERN DOTS-28
+noback sign \x2883 128 # ⢃ BRAILLE PATTERN DOTS-128
+noback sign \x2884 38 # ⢄ BRAILLE PATTERN DOTS-38
+noback sign \x2885 138 # ⢅ BRAILLE PATTERN DOTS-138
+noback sign \x2886 238 # ⢆ BRAILLE PATTERN DOTS-238
+noback sign \x2887 1238 # ⢇ BRAILLE PATTERN DOTS-1238
+noback sign \x2888 48 # ⢈ BRAILLE PATTERN DOTS-48
+noback sign \x2889 148 # ⢉ BRAILLE PATTERN DOTS-148
+noback sign \x288A 248 # ⢊ BRAILLE PATTERN DOTS-248
+noback sign \x288B 1248 # ⢋ BRAILLE PATTERN DOTS-1248
+noback sign \x288C 348 # ⢌ BRAILLE PATTERN DOTS-348
+noback sign \x288D 1348 # ⢍ BRAILLE PATTERN DOTS-1348
+noback sign \x288E 2348 # ⢎ BRAILLE PATTERN DOTS-2348
+noback sign \x288F 12348 # ⢏ BRAILLE PATTERN DOTS-12348
+noback sign \x2890 58 # ⢐ BRAILLE PATTERN DOTS-58
+noback sign \x2891 158 # ⢑ BRAILLE PATTERN DOTS-158
+noback sign \x2892 258 # ⢒ BRAILLE PATTERN DOTS-258
+noback sign \x2893 1258 # ⢓ BRAILLE PATTERN DOTS-1258
+noback sign \x2894 358 # ⢔ BRAILLE PATTERN DOTS-358
+noback sign \x2895 1358 # ⢕ BRAILLE PATTERN DOTS-1358
+noback sign \x2896 2358 # ⢖ BRAILLE PATTERN DOTS-2358
+noback sign \x2897 12358 # ⢗ BRAILLE PATTERN DOTS-12358
+noback sign \x2898 458 # ⢘ BRAILLE PATTERN DOTS-458
+noback sign \x2899 1458 # ⢙ BRAILLE PATTERN DOTS-1458
+noback sign \x289A 2458 # ⢚ BRAILLE PATTERN DOTS-2458
+noback sign \x289B 12458 # ⢛ BRAILLE PATTERN DOTS-12458
+noback sign \x289C 3458 # ⢜ BRAILLE PATTERN DOTS-3458
+noback sign \x289D 13458 # ⢝ BRAILLE PATTERN DOTS-13458
+noback sign \x289E 23458 # ⢞ BRAILLE PATTERN DOTS-23458
+noback sign \x289F 123458 # ⢟ BRAILLE PATTERN DOTS-123458
+noback sign \x28A0 68 # ⢠ BRAILLE PATTERN DOTS-68
+noback sign \x28A1 168 # ⢡ BRAILLE PATTERN DOTS-168
+noback sign \x28A2 268 # ⢢ BRAILLE PATTERN DOTS-268
+noback sign \x28A3 1268 # ⢣ BRAILLE PATTERN DOTS-1268
+noback sign \x28A4 368 # ⢤ BRAILLE PATTERN DOTS-368
+noback sign \x28A5 1368 # ⢥ BRAILLE PATTERN DOTS-1368
+noback sign \x28A6 2368 # ⢦ BRAILLE PATTERN DOTS-2368
+noback sign \x28A7 12368 # ⢧ BRAILLE PATTERN DOTS-12368
+noback sign \x28A8 468 # ⢨ BRAILLE PATTERN DOTS-468
+noback sign \x28A9 1468 # ⢩ BRAILLE PATTERN DOTS-1468
+noback sign \x28AA 2468 # ⢪ BRAILLE PATTERN DOTS-2468
+noback sign \x28AB 12468 # ⢫ BRAILLE PATTERN DOTS-12468
+noback sign \x28AC 3468 # ⢬ BRAILLE PATTERN DOTS-3468
+noback sign \x28AD 13468 # ⢭ BRAILLE PATTERN DOTS-13468
+noback sign \x28AE 23468 # ⢮ BRAILLE PATTERN DOTS-23468
+noback sign \x28AF 123468 # ⢯ BRAILLE PATTERN DOTS-123468
+noback sign \x28B0 568 # ⢰ BRAILLE PATTERN DOTS-568
+noback sign \x28B1 1568 # ⢱ BRAILLE PATTERN DOTS-1568
+noback sign \x28B2 2568 # ⢲ BRAILLE PATTERN DOTS-2568
+noback sign \x28B3 12568 # ⢳ BRAILLE PATTERN DOTS-12568
+noback sign \x28B4 3568 # ⢴ BRAILLE PATTERN DOTS-3568
+noback sign \x28B5 13568 # ⢵ BRAILLE PATTERN DOTS-13568
+noback sign \x28B6 23568 # ⢶ BRAILLE PATTERN DOTS-23568
+noback sign \x28B7 123568 # ⢷ BRAILLE PATTERN DOTS-123568
+noback sign \x28B8 4568 # ⢸ BRAILLE PATTERN DOTS-4568
+noback sign \x28B9 14568 # ⢹ BRAILLE PATTERN DOTS-14568
+noback sign \x28BA 24568 # ⢺ BRAILLE PATTERN DOTS-24568
+noback sign \x28BB 124568 # ⢻ BRAILLE PATTERN DOTS-124568
+noback sign \x28BC 34568 # ⢼ BRAILLE PATTERN DOTS-34568
+noback sign \x28BD 134568 # ⢽ BRAILLE PATTERN DOTS-134568
+noback sign \x28BE 234568 # ⢾ BRAILLE PATTERN DOTS-234568
+noback sign \x28BF 1234568 # ⢿ BRAILLE PATTERN DOTS-1234568
+noback sign \x28C0 78 # ⣀ BRAILLE PATTERN DOTS-78
+noback sign \x28C1 178 # ⣁ BRAILLE PATTERN DOTS-178
+noback sign \x28C2 278 # ⣂ BRAILLE PATTERN DOTS-278
+noback sign \x28C3 1278 # ⣃ BRAILLE PATTERN DOTS-1278
+noback sign \x28C4 378 # ⣄ BRAILLE PATTERN DOTS-378
+noback sign \x28C5 1378 # ⣅ BRAILLE PATTERN DOTS-1378
+noback sign \x28C6 2378 # ⣆ BRAILLE PATTERN DOTS-2378
+noback sign \x28C7 12378 # ⣇ BRAILLE PATTERN DOTS-12378
+noback sign \x28C8 478 # ⣈ BRAILLE PATTERN DOTS-478
+noback sign \x28C9 1478 # ⣉ BRAILLE PATTERN DOTS-1478
+noback sign \x28CA 2478 # ⣊ BRAILLE PATTERN DOTS-2478
+noback sign \x28CB 12478 # ⣋ BRAILLE PATTERN DOTS-12478
+noback sign \x28CC 3478 # ⣌ BRAILLE PATTERN DOTS-3478
+noback sign \x28CD 13478 # ⣍ BRAILLE PATTERN DOTS-13478
+noback sign \x28CE 23478 # ⣎ BRAILLE PATTERN DOTS-23478
+noback sign \x28CF 123478 # ⣏ BRAILLE PATTERN DOTS-123478
+noback sign \x28D0 578 # ⣐ BRAILLE PATTERN DOTS-578
+noback sign \x28D1 1578 # ⣑ BRAILLE PATTERN DOTS-1578
+noback sign \x28D2 2578 # ⣒ BRAILLE PATTERN DOTS-2578
+noback sign \x28D3 12578 # ⣓ BRAILLE PATTERN DOTS-12578
+noback sign \x28D4 3578 # ⣔ BRAILLE PATTERN DOTS-3578
+noback sign \x28D5 13578 # ⣕ BRAILLE PATTERN DOTS-13578
+noback sign \x28D6 23578 # ⣖ BRAILLE PATTERN DOTS-23578
+noback sign \x28D7 123578 # ⣗ BRAILLE PATTERN DOTS-123578
+noback sign \x28D8 4578 # ⣘ BRAILLE PATTERN DOTS-4578
+noback sign \x28D9 14578 # ⣙ BRAILLE PATTERN DOTS-14578
+noback sign \x28DA 24578 # ⣚ BRAILLE PATTERN DOTS-24578
+noback sign \x28DB 124578 # ⣛ BRAILLE PATTERN DOTS-124578
+noback sign \x28DC 34578 # ⣜ BRAILLE PATTERN DOTS-34578
+noback sign \x28DD 134578 # ⣝ BRAILLE PATTERN DOTS-134578
+noback sign \x28DE 234578 # ⣞ BRAILLE PATTERN DOTS-234578
+noback sign \x28DF 1234578 # ⣟ BRAILLE PATTERN DOTS-1234578
+noback sign \x28E0 678 # ⣠ BRAILLE PATTERN DOTS-678
+noback sign \x28E1 1678 # ⣡ BRAILLE PATTERN DOTS-1678
+noback sign \x28E2 2678 # ⣢ BRAILLE PATTERN DOTS-2678
+noback sign \x28E3 12678 # ⣣ BRAILLE PATTERN DOTS-12678
+noback sign \x28E4 3678 # ⣤ BRAILLE PATTERN DOTS-3678
+noback sign \x28E5 13678 # ⣥ BRAILLE PATTERN DOTS-13678
+noback sign \x28E6 23678 # ⣦ BRAILLE PATTERN DOTS-23678
+noback sign \x28E7 123678 # ⣧ BRAILLE PATTERN DOTS-123678
+noback sign \x28E8 4678 # ⣨ BRAILLE PATTERN DOTS-4678
+noback sign \x28E9 14678 # ⣩ BRAILLE PATTERN DOTS-14678
+noback sign \x28EA 24678 # ⣪ BRAILLE PATTERN DOTS-24678
+noback sign \x28EB 124678 # ⣫ BRAILLE PATTERN DOTS-124678
+noback sign \x28EC 34678 # ⣬ BRAILLE PATTERN DOTS-34678
+noback sign \x28ED 134678 # ⣭ BRAILLE PATTERN DOTS-134678
+noback sign \x28EE 234678 # ⣮ BRAILLE PATTERN DOTS-234678
+noback sign \x28EF 1234678 # ⣯ BRAILLE PATTERN DOTS-1234678
+noback sign \x28F0 5678 # ⣰ BRAILLE PATTERN DOTS-5678
+noback sign \x28F1 15678 # ⣱ BRAILLE PATTERN DOTS-15678
+noback sign \x28F2 25678 # ⣲ BRAILLE PATTERN DOTS-25678
+noback sign \x28F3 125678 # ⣳ BRAILLE PATTERN DOTS-125678
+noback sign \x28F4 35678 # ⣴ BRAILLE PATTERN DOTS-35678
+noback sign \x28F5 135678 # ⣵ BRAILLE PATTERN DOTS-135678
+noback sign \x28F6 235678 # ⣶ BRAILLE PATTERN DOTS-235678
+noback sign \x28F7 1235678 # ⣷ BRAILLE PATTERN DOTS-1235678
+noback sign \x28F8 45678 # ⣸ BRAILLE PATTERN DOTS-45678
+noback sign \x28F9 145678 # ⣹ BRAILLE PATTERN DOTS-145678
+noback sign \x28FA 245678 # ⣺ BRAILLE PATTERN DOTS-245678
+noback sign \x28FB 1245678 # ⣻ BRAILLE PATTERN DOTS-1245678
+noback sign \x28FC 345678 # ⣼ BRAILLE PATTERN DOTS-345678
+noback sign \x28FD 1345678 # ⣽ BRAILLE PATTERN DOTS-1345678
+noback sign \x28FE 2345678 # ⣾ BRAILLE PATTERN DOTS-2345678
+noback sign \x28FF 12345678 # ⣿ BRAILLE PATTERN DOTS-12345678
+
+
+# ----------------------------------------------------------------------------------------------
+
diff --git a/vendor/liblouis/src/louis/tables/en-ueb-chardefs.uti b/vendor/liblouis/src/louis/tables/en-ueb-chardefs.uti
new file mode 100644
index 0000000..b0e5c49
--- /dev/null
+++ b/vendor/liblouis/src/louis/tables/en-ueb-chardefs.uti
@@ -0,0 +1,938 @@
+# liblouis: English (Unified) character definitions table
+#
+# Based on the Linux screenreader BRLTTY
+#
+# Copyright (C) 1999-2006 by The BRLTTY Team
+# Copyright (C) 2004-2006 ViewPlus Technologies, Inc. www.viewplus.com
+# Copyright (C) 2004-2006 JJB Software, Inc. www.jjb-software.com
+# Copyright (C) 2016 American Printing House for the Blind, Inc. www.aph.org
+# Copyright (C) 2020 RNIB, www.rnib.org.uk
+#
+# This file is part of liblouis.
+#
+# liblouis is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation, either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# liblouis is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with liblouis. If not, see
+# .
+
+#-maintainer: James Bowden
+
+space \t 9 tab
+space \x001b 1b escape character for html back-translation
+space \x00A0 a NO-BREAK SPACE 0020 NON-BREAKING SPACE
+
+noback correct "\x200b" "\s"
+
+include text_nabcc.dis
+include spaces.uti
+
+include latinLetterDef6Dots.uti
+include latinUppercaseComp6.uti
+
+
+# Modifiers
+
+# acute accent
+sign \x00b4 45-34 ´
+sign \x0301 45-34 ́
+noback correct [$l]"́" "́"*
+
+# circumflex/carot
+sign \x005e 4-26 ^
+sign \x0302 45-146 ̂
+noback correct [$l]"̂" "̂"*
+
+# grave accent
+sign \x0060 46-16 `
+noback punctuation ` 4
+sign \x0300 45-16 ̀̀
+noback correct [$l]"̀" "̀"*
+
+# tilde
+math \x007e 4-35 ~
+sign \x0303 45-12456 ̃
+noback correct [$l]"̃" "̃"*
+noback pass2 @45-12456-6 @6-45-12456 move after capital sign
+
+# macron
+sign \x00af 4-36 ¯
+sign \x0304 4-36 ̄
+noback correct [$l]"̄" "̄"*
+
+# cedilla
+sign \x00b8 45-12346 ¸
+sign \x0327 45-12346 ̧
+noback correct [$l]"̧" "̧"*
+
+# diaeresis/umlat
+sign \x00a8 45-25 ¨
+sign \x0308 45-25 ̈
+noback correct [$l]"̈" "̈"*
+
+# caron
+sign \x02c7 45-345 ˇ
+sign \x030c 45-346 ̌
+noback correct [$l]"̌" "̌"*
+
+# breve
+sign \x02d8 4-346 ˘
+sign \x0306 4-346 ̆
+noback correct [$l]"̆" "̆"*
+
+# ring/circle
+sign \x02da 45-1246 ˚
+sign \x030a 45-1246 ̊
+noback correct [$l]"̊" "̊"*
+
+
+##### Start of Unicode
+
+
+# Unicode: Basic Latin
+
+punctuation ! 235
+nofor postpunc ! 235
+match %a ! %a 56-235
+
+punctuation " 6-2356
+# The "?" symbol is mostly handled below,
+# but the pattern needs to be defined before prepunc and postpunc can be used.
+nofor punctuation ? 236
+nofor punctuation " 356
+nofor prepunc " 236
+nofor postpunc " 356
+match %[^_~]%<* " %[_.$]*%[a#] 236
+match %[a#]%[_.$]* " %>*%[^_~] 356
+
+sign # 456-1456
+sign $ 4-234
+sign % 46-356
+sign & 4-12346
+punctuation ' 3
+punctuation ( 5-126
+nofor prepunc ( 5-126
+punctuation ) 5-345
+postpunc ) 5-345
+sign * 5-35
+math + 5-235
+punctuation , 2
+nofor postpunc , 2
+match %a , %a 56-2
+punctuation - 36
+hyphen - 36
+punctuation . 256
+nofor postpunc . 256
+math / 456-34
+# 0-9 see Numeric Symbols
+punctuation : 25
+postpunc : 25
+match %a : %a 56-25
+punctuation ; 23
+postpunc ; 23
+match %a ; %a 56-23
+math < 4-126
+math = 5-2356
+punctuation > 4-345
+# requires grade one indicator when by itself
+punctuation ? 56-236
+postpunc ? 236
+sign @ 4-1
+# A-Z see latinLetterDef8Dots.uti
+punctuation [ 46-126
+nofor prepunc [ 46-126
+sign \\ 456-16
+punctuation ] 46-345
+nofor postpunc ] 46-345
+# \x005e ^ see Modifiers
+sign _ 46-36
+# /x0060 ` see Modifiers
+# a-z see latinLetterDef8Dots.uti
+punctuation { 456-126
+nofor prepunc { 456-126
+sign | 456-1256
+punctuation } 456-345
+nofor postpunc } 456-345
+# \x007e ~ see Modifiers
+
+
+# Unicode: Latin-1 Supplement
+
+#punctuation \x0093 236
+#punctuation \x0094 356
+#punctuation \x0096 36
+space \x00a0 a non-breaking space
+sign \x00a1 45-56-235 ¡
+punctuation \x00a1 235 ¡
+sign \x00a2 4-14 ¢ cent
+sign \x00a3 4-123 £ pound
+sign \x00a4 1246 ¤ curency
+sign \x00a5 4-13456 ¥ yen
+sign \x00a6 46-1256 ¦ broken bar
+punctuation \x00a6 456-1256 ¦ broken bar
+sign \x00a7 45-234 § section
+# \x00a8 ¨ see Modifiers
+sign \x00a9 45-14 © copyright
+#sign \x00aa ª
+punctuation \x00ab 456-236 «
+sign \x00ac 4-1456 ¬
+punctuation \x00ad 36 - soft hyphen
+sign \x00ae 45-1235 ® registered
+# \x00af ¯ see Modifiers
+sign \x00b0 45-245 °
+math \x00b1 456-235 ±
+
+# fake grade 1 and superscript indicator
+math \x00b2 56-35-3456-12 ²
+math \x00b3 56-35-3456-14 ³
+
+# \x00b4 ´ see Modifiers
+sign \x00b5 46-134 µ
+math \x00b7 4-16 ·
+
+# fake numeric indicator
+math \x00bc 3456-1-34-145 ¼
+math \x00bd 3456-1-34-12 ½
+math \x00be 3456-14-34-145 ¾
+
+#sign \x00ba 0 º
+sign \x00b6 45-1234 ¶ pilcrow
+# \x00b8 ¸ see Modifiers
+punctuation \x00bb 456-356 »
+punctuation \x00bf 45-56-236 ¿
+lowercase \x00df 46-2346 ß
+lowercase \x00e0 45-16-1 à
+lowercase \x00e1 45-34-1 á
+lowercase \x00e2 45-146-1 â
+lowercase \x00e3 45-12456-1 ã
+lowercase \x00e4 45-25-1 ä
+lowercase \x00e5 45-1246-1 å
+lowercase \x00e6 1-6-45-235-15 æ if needed the dot 6 is removed in pass2 (see below)
+lowercase \x00e7 45-12346-14 ç
+lowercase \x00e8 45-16-15 è
+lowercase \x00e9 45-34-15 é
+lowercase \x00ea 45-146-15 ê
+lowercase \x00eb 45-25-15 ë
+lowercase \x00ec 45-16-24 ì
+lowercase \x00ed 45-34-24 í
+lowercase \x00ee 45-146-24 î
+lowercase \x00ef 45-25-24 ï
+lowercase \x00f0 3456-1246 ð
+lowercase \x00f1 45-12456-1345 ñ
+lowercase \x00f2 45-16-135 ò
+lowercase \x00f3 45-34-135 ó
+lowercase \x00f4 45-146-135 ô
+lowercase \x00f5 45-12456-135 õ
+lowercase \x00f6 45-25-135 ö
+math \x00d7 5-236 ×
+lowercase \x00f8 4-16-135 Øø
+lowercase \x00f9 45-16-136 ù
+lowercase \x00fa 45-34-136 ú
+lowercase \x00fb 45-146-136 û
+lowercase \x00fc 45-25-136 ü
+lowercase \x00fd 45-34-13456 ý
+lowercase \x00fe 3456-2346 þ
+math \x00f7 5-34 ÷
+
+
+# Unicode: Latin Extended-A
+
+lowercase \x0101 4-36-1 ā
+lowercase \x0103 4-346-1 ă
+lowercase \x0107 45-34-14 ć
+lowercase \x0109 45-146-14 ĉ
+lowercase \x010d 45-346-14 č
+lowercase \x010f 45-346-145 ď
+lowercase \x0111 4-25-145 đ
+lowercase \x0113 4-36-15 ē
+lowercase \x0115 4-346-15 ĕ
+lowercase \x011b 45-346-15 ě
+lowercase \x011d 45-146-1245 ĝ
+lowercase \x011f 4-346-1245 ğ
+lowercase \x0123 45-12346-1245 ģ
+lowercase \x0125 45-146-125 ĥ
+lowercase \x0127 4-25-125 ħ
+lowercase \x0129 45-12456-24 ĩ
+lowercase \x012b 4-36-24 ī
+lowercase \x012d 4-346-24 ĭ
+lowercase \x0133 24-6-45-235-245 IJij if needed the dot 6 is removed in pass2 (see below)
+lowercase \x0135 45-146-245 ĵ
+lowercase \x0137 45-12346-13 ķ
+lowercase \x013a 45-34-123 ĺ
+lowercase \x013c 45-12346-123 ļ
+lowercase \x013e 45-346-123 ľ
+lowercase \x0142 4-16-123 ł
+lowercase \x0144 45-34-1345 ń
+lowercase \x0146 45-12346-1345 ņ
+lowercase \x0148 45-346-1345 ň
+lowercase \x014b 45-1345 ŋ
+lowercase \x014d 4-36-135 ō
+lowercase \x014f 4-346-135 ŏ
+lowercase \x0153 135-6-45-235-15 œ if needed the dot 6 is removed in pass2 (see below)
+lowercase \x0155 45-34-1235 ŕ
+lowercase \x0157 45-12346-1235 ŗ
+lowercase \x0159 45-346-1235 ř
+lowercase \x015b 45-34-234 ś
+lowercase \x015d 45-146-234 ŝ
+lowercase \x015f 45-12346-234 ş
+lowercase \x0161 45-346-234 š
+lowercase \x0163 45-12346-2345 ţ
+lowercase \x0165 45-346-2345 ť
+lowercase \x0167 4-25-2345 ŧ
+lowercase \x0169 45-12456-136 ũ
+lowercase \x016b 4-36-136 ū
+lowercase \x016d 4-346-136 ŭ
+lowercase \x016f 45-1246-136 ů
+lowercase \x0175 45-146-2456 ŵ
+lowercase \x0177 45-146-13456 ŷ
+lowercase \x00ff 45-25-13456 ÿ
+lowercase \x017a 45-34-1356 ź
+lowercase \x017e 45-346-1356 ž
+
+
+# Unicode: Latin Extended-B
+
+lowercase \x0259 456-26 ə schwa e must be before \x018e and \x04d8
+lowercase \x01dd 456-26 ǝ turned e
+lowercase \x0268 4-25-24 ɨ
+lowercase \x01b6 4-25-1356 ƶ
+lowercase \x01ce 45-346-1 ǎ
+lowercase \x01d0 45-346-24 ǐ
+lowercase \x01d2 45-346-135 ǒ
+lowercase \x01d4 45-346-136 ǔ
+lowercase \x01e5 4-25-1245 ǥ
+lowercase \x01e7 45-346-1245 ǧ
+lowercase \x01e9 45-346-13 ǩ
+lowercase \x01f5 45-34-1245 ǵ
+lowercase \x01f0 45-346-245 ǰ
+lowercase \x01bf 3456-2456 ƿ wynn
+lowercase \x01f9 45-16-1345 ǹ
+
+lowercase \x021d 3456-13456 ȝ yogh
+lowercase \x021f 45-346-125 ȟ
+lowercase \x0229 45-12346-15 ȩ
+lowercase \x0233 4-36-13456 ȳ
+lowercase \x2c65 4-16-1 ⱥ
+lowercase \x023c 4-16-14 ȼ
+lowercase \x2c66 4-16-2345 ⱦ
+lowercase \x0180 4-25-12 ƀ
+lowercase \x0247 4-16-15 ɇ
+lowercase \x0249 4-25-245 Ɉ
+lowercase \x024d 4-25-1235 ɍ
+lowercase \x024f 4-25-13456 ɏ
+
+
+# Unicode: IPA Extensions
+
+# \x0259 ə see \x018f
+
+
+# Unicode: Spacing Modifier Letters
+
+sign \x02e6 45-46-14 ˦ high tone
+sign \x02e7 45-46-25 ˧ mid tone
+sign \x02e8 45-46-36 ˨ low tone
+
+
+# Unicode: Greek and Coptic
+
+lowercase \x03b1 46-1 α Alpha
+lowercase \x03b2 46-12 β Beta
+lowercase \x03b3 46-1245 γ Gamma
+lowercase \x03b4 46-145 δ Delta
+lowercase \x03b5 46-15 ε Epsilon
+lowercase \x03b6 46-1356 ζ Zeta
+lowercase \x03b7 46-156 η Eta
+lowercase \x03b8 46-1456 θ Theta
+lowercase \x03b9 46-24 ι Iota
+lowercase \x03ba 46-13 κ Kappa
+lowercase \x03bb 46-123 λ Lamda
+lowercase \x03bc 46-134 μ Mu
+lowercase \x03bd 46-1345 ν Nu
+lowercase \x03be 46-1346 ξ Xi
+lowercase \x03bf 46-135 ο Omicron
+lowercase \x03c0 46-1234 π Pi
+lowercase \x03c1 46-1235 ρ Rho
+lowercase \x03c3 46-234 σ Sigma
+lowercase \x03c4 46-2345 τ Tau
+lowercase \x03c5 46-136 υ Upsilon
+lowercase \x03c6 46-124 φ Phi
+lowercase \x03c7 46-12346 χ Chi
+lowercase \x03c8 46-13456 ψ Psi
+lowercase \x03c9 46-2456 ω Omega
+noback lowercase \x03c2 46-234 ς Small Letter Sigma
+
+
+# Unicode: Cyrillic
+# similar cyrillic characters must be after latin characters
+# to ensure proper backward translation
+
+
+# Unicode: Latin Extended Additional
+
+lowercase \x1e11 45-12346-145 ḑ
+lowercase \x1e21 4-36-1245 ḡ
+lowercase \x1e27 45-25-125 ḧ
+lowercase \x1e29 45-12346-125 ḩ
+lowercase \x1e31 45-34-13 ḱ
+lowercase \x1e3f 45-34-134 ḿ
+lowercase \x1e55 45-34-1234 ṕ
+lowercase \x1e7d 45-12456-1236 ṽ
+lowercase \x1e81 45-16-2456 ẁ
+lowercase \x1e83 45-34-2456 ẃ
+lowercase \x1e85 45-25-2456 ẅ
+lowercase \x1e8d 45-25-1346 ẍ
+lowercase \x1e91 45-146-1356 ẑ
+lowercase \x1e97 45-25-2345 ẗ
+lowercase \x1e98 45-1246-2456 ẘ http://archives.miloush.net/michkap/archive/2012/04/17/10294366.html
+lowercase \x1e99 45-1246-13456 ẙ
+lowercase \x1ebd 45-12456-15 ẽ
+lowercase \x1ef3 45-16-13456 ỳ
+lowercase \x1ef9 45-12456-13456 ỹ
+
+
+# Unicode: General Punctuation
+
+space \x2000 0
+space \x2001 0
+space \x2002 0
+space \x2003 0
+space \x2004 0
+space \x2005 0
+space \x2006 0
+space \x2007 0
+space \x2008 0
+space \x2009 0
+space \x200a 0
+space \x200b 0
+punctuation \x2010 36 ‐
+punctuation \x2011 36 ‑
+noback punctuation \x2013 6-36 – backtranslate as \x2014
+punctuation \x2014 6-36 — Rules of UEB, App.3
+punctuation \x2015 5-6-36 ―
+noback punctuation \x2018 6-236 ‘
+noback punctuation \x2019 6-356 ’
+match %a \x2019 %a 3 # single quote between letters is really apostrophe
+punctuation \x201c 236 “
+punctuation \x201d 356 ”
+sign \x2020 4-6-1456 † dagger
+sign \x2021 4-6-12456 ‡ double dagger
+sign \x2022 456-256 • bullet
+punctuation \x2026 256-256-256 … ellipsis
+space \x202f 0 narrow no-break space
+sign \x2032 2356 ′ prime (derivative)
+sign \x2033 2356-2356 ″ double prime (second derivative)
+
+
+# Unicode: Superscripts and Subscripts
+
+# fake indicators and numeric indicator
+#math \x2070 35-3456-245 ⁰
+
+
+# Unicode: Currency Symbols
+
+sign \x20a3 4-124 ₣ franc
+sign \x20a6 4-1345 ₦ naira
+sign \x20ac 4-15 € euro
+
+
+# Unicode: Letterlike Symbols
+
+sign \x2122 45-2345 ™
+noback sign \x2126 6-46-2456 Ω Ohm sign, same as capital Omega
+noback sign \x212b 6-45-1246-1 Å Angstrom same as capital A with ring
+
+# Unicode: Number Forms
+
+# fake numerical indicator for simple fractions
+math \x2150 3456-1-34-1245 ⅐
+math \x2151 3456-1-34-24 ⅑
+math \x2152 3456-1-34-1-245 ⅒
+math \x2153 3456-1-34-14 ⅓
+math \x2154 3456-12-34-14 ⅔
+math \x2155 3456-1-34-15 ⅕
+math \x2156 3456-12-34-15 ⅖
+math \x2157 3456-14-34-15 ⅗
+math \x2158 3456-145-34-15 ⅘
+math \x2159 3456-1-34-124 ⅙
+math \x215a 3456-15-34-124 ⅚
+math \x215b 3456-1-34-125 ⅛
+math \x215c 3456-14-34-125 ⅜
+math \x215d 3456-15-34-125 ⅝
+math \x215e 3456-1245-34-125 ⅞
+math \x2189 3456-245-34-14 ↉
+
+
+# Unicode: Arrows
+
+sign \x2190 56-1256-246 ←
+sign \x2191 56-1256-346 ↑
+sign \x2192 56-1256-135 →
+sign \x2193 56-1256-146 ↓
+sign \x2196 56-1256-156 ↖
+sign \x2197 56-1256-234 ↗
+sign \x2198 56-1256-126 ↘
+sign \x2199 56-1256-345 ↙
+sign \x21a6 56-1256-1256 ↦
+sign \x21b2 56-1256-256 ↲
+sign \x21b3 56-1256-356 ↳
+sign \x21b5 56-1256-256-146 ↵ Rules of UEB, page 21
+sign \x21c0 56-1256-4-1235 ⇀
+sign \x21c1 56-1256-6-1235 ⇁
+sign \x21cc 45-456-2356 ⇌ equilibrium arrow (harpoons)
+sign \x21d0 56-1256-2356-246 ⇐
+sign \x21d1 56-1256-2356-346 ⇑
+sign \x21d2 56-1256-2356-135 ⇒
+sign \x21d3 56-1256-2356-146 ⇓
+
+# Unicode: Mathematical Operators
+
+sign \x2200 45-1 ∀ for all
+sign \x2202 4-145 ∂ partial derivative
+sign \x2203 45-26 ∃ there exists
+sign \x2204 45-26-4-156 ∄ there does not exist
+sign \x2205 4-245 ∅ empty set
+noback sign \x2206 6-46-145 ∆ Increment same as capital Delta
+sign \x2207 45-145 ∇ nabla
+sign \x2208 45-15 ∈ element of
+sign \x2209 45-15-4-156 ∉ not an element of
+sign \x220b 4-45-15 ∋ contains (such that)
+sign \x220c 4-45-15-4-156 ∌ does not contain as member
+sign \x220f 6-46-1234 ∏ product (capital pi)
+sign \x2211 6-46-234 ∑ sum (capitol sigma)
+sign \x2212 5-36 − minus sign (not hyphen)
+sign \x2213 456-36 ∓ minus or plus
+noback sign \x2216 456-16 ∖ set minus
+noback sign \x2217 5-35 ∗ asterisk operator
+sign \x2218 5-356 ∘ hollow dot (ring operator)
+sign \x221a 5-146 √ square root
+sign \x221d 456-5-2356 ∝ proportional to
+sign \x221e 3456-123456 ∞ infinity
+sign \x2220 456-246 ∠ angle
+sign \x2221 46-456-246 ∡ measured angle
+noback sign \x2223 456-1256 ∣ divides
+sign \x2224 456-1256-4-156 ∤ does not divide
+sign \x2225 3456-123 ∥ parallel to
+sign \x2226 3456-123-4-156 ∦ not parallel to
+sign \x2227 4-236 ∧ logical and
+sign \x2228 4-235 ∨ logical or
+sign \x2229 46-236 ∩ set intersection
+sign \x222a 46-235 ∪ set union
+sign \x222b 2346 ∫ integral
+sign \x222e 4-2346 contour integral
+noback sign \x2234 6-16 ∴ therefore # using noback to avoid conflict with Child
+sign \x2235 4-34 ∵ because
+noback sign \x2236 25 ∶ ratio # using noback to avoid conflict with :
+sign \x2237 25-25 ∷ proportion
+noback sign \x223c 4-35 ∼ tilde operator
+sign \x2241 4-35-4-156 ≁ not tilde
+sign \x2243 456-35 ≃ asymptotically equal to
+sign \x2244 456-35-4-156 ≄ not asymptotically equal
+sign \x2245 5-456-35 ≅ approximately equal to
+sign \x2247 5-456-35-4-156 ≇ neither approximately nor actually equal
+sign \x2248 45-35 ≈ almost equal to
+sign \x2249 45-35-4-156 ≉ not almost equal
+sign \x224f 45-5-2356 ≏ difference between
+sign \x2251 46-5-2356 ≑ geometrically equal
+sign \x2260 5-2356-4-156 ≠ not equal
+sign \x2261 456-123456 ≡ identical (equivalent) to
+sign \x2262 456-123456-4-156 ≢ not identical to
+sign \x2264 456-4-126 ≤ less than or equal to
+sign \x2265 456-4-345 ≥ greater than or equal to
+sign \x226a 46-4-126 ≪ much less than
+sign \x226b 46-4-345 ≫ much greater than
+sign \x226e 4-126-4-156 ≮ not less than
+sign \x226f 4-345-4-156 ≯ not greater than
+sign \x2270 456-4-126-4-156 ≰ neither less than nor equal to
+sign \x2271 456-4-345-4-156 ≱ neither greather than nor equal to
+sign \x2282 45-126 ⊂ subset of
+sign \x2283 45-345 ⊃ superset of
+sign \x2284 45-126-4-156 ⊄ not subset of
+sign \x2285 45-345-4-156 ⊅ not superset of
+sign \x2286 456-45-126 ⊆ subset or equal to
+sign \x2287 456-45-345 ⊇ superset or equal to
+sign \x2288 456-45-126-4-156 ⊈ neither a subset nor equal
+sign \x2289 456-45-345-4-156 ⊉ neither a superset nor equal
+sign \x228a 46-45-126 ⊊ proper subset
+sign \x228b 46-45-345 ⊋ proper superset
+noback sign \x22a2 456-25 ⊢ right tack
+sign \x22a3 4-456-25 ⊣ left tack
+sign \x22a5 3456-36 ⊥ up tack
+sign \x22a6 456-25 ⊦ assertion
+sign \x22a8 45-456-25 ⊨ valid
+sign \x22ac 456-25-4-156 ⊬ does not prove
+sign \x22ad 45-456-25-4-156 ⊭ not true
+sign \x22b2 4-456-126 ⊲ normal subgroup
+sign \x22b3 4-456-345 ⊳ contains as normal subgroup
+sign \x22b4 456-456-126 ⊴ normal subgroup or equal
+sign \x22b5 456-456-345 ⊵ contains as normal subgroup or equal
+sign \x22be 3456-456-246 ⊾ right angle with arc
+sign \x22c5 5-256 ⋅ dot operator
+sign \x22ea 4-456-126-4-156 ⋪ not normal subgroup
+sign \x22eb 4-456-345-4-156 ⋫ does not contain as normal subgroup
+sign \x22ec 456-456-126-4-156 ⋬ not normal subgroup nor equal
+sign \x22ed 456-456-345-4-156 ⋭ does not contain as normal subgroup nor equal
+
+# Unicode: Miscellaneous Technical
+
+math \x2329 4-126 〈
+math \x232A 4-345 〉
+
+
+# Unicode: Box Drawing
+
+noback sign \x2502 456 │ tally mark - vertical single solid line segment
+noback sign \x250a 45 ┊ first variant vertical line segment
+noback sign \x2551 6-456 ║ second variant vertical line segment
+noback sign \x2571 345 ╱ right-leaning single solid diagonal line segment # using noback to avoid conflict with "ar" contraction
+noback sign \x2572 126 ╲ left-leaning single solid diagonal line segment # using noback to avoid conflict with "gh" contraction
+
+
+# Unicode: Geometric Shapes
+
+sign \x25a0 456-1246-3456-145 ■ filled (solid) square
+sign \x25a1 1246-3456-145 □ square
+sign \x25a7 46-1246-3456-145 ▧ shaded square (upper left to lower right)
+sign \x25b2 456-1246-3456-14 ▲ filled (solid) (equilateral) triangle
+sign \x25b3 1246-3456-14 △ regular (equilateral) triangle
+sign \x25cb 1246-123456 ○ circle
+sign \x25cd 46-1246-123456 ◍ shaded circle
+sign \x25aa 456-256 ▪
+noback sign \x25cf 5-35 ● black circle # not representing filled circle shape as it is mostly used in password fields to represent hidden characters
+
+
+# Unicode: Miscellaneous Symbols
+
+sign \x2640 45-1346 ♀
+sign \x2642 45-13456 ♂
+sign \x266D 3456-126 ♭
+sign \x266E 3456-16 ♮
+sign \x266F 3456-146 ♯
+
+
+# Unicode: Dingbats
+
+sign \x2713 4-146 ✓ check mark
+noback sign \x2714 4-146 ✔ check mark
+
+
+# Unicode: Miscellaneous Mathematical Symbols-A
+
+noback sign \x27c2 3456-36 ⟂ perpendicular
+
+
+# Unicode: Miscellaneous Mathematical Symbols-B
+
+sign \x2980 3456-456-123 ⦀ triple vertical bar delimiter
+sign \x29b5 46-245 ⦵ 'normal' (superscript circle crossed by horizontal line)
+
+
+# Unicode: Supplemental Mathematical Operators
+
+sign \x2a23 45-146-5-235 ⨣
+sign \x2a24 45-12456-5-235 ⨤
+sign \x2ae4 46-456-25 ⫤ reverse 'is valid' sign
+noback sign \x2af4 3456-456-123 ⫴ triple vertical bar binary relation
+noback sign \x2afc 3456-456-123 ⫼ large triple vertical bar operator
+
+
+# Unicode: Latin Extended-C
+
+lowercase \x1d7d 4-25-1234 ᵽ
+
+
+# Unicode: CJK Symbols and Punctuation
+
+sign \x3003 5-2 〃 ditto mark
+math \x3008 4-126 〈
+math \x3009 4-345 〉
+
+
+# Unicode: Latin Extended-D
+
+lowercase \xa741 4-25-13 ꝁ
+lowercase \xa743 4-16-13 ꝃ
+lowercase \xa751 4-25-1234 ꝑ
+lowercase \xa757 4-25-12345 ꝗ
+lowercase \xa759 4-16-12345 ꝙ
+lowercase \xa75f 4-16-1236 ꝟ
+lowercase \xa799 4-25-124 ꞙ
+
+
+# Unicode: Latin Extended-D
+
+lowercase \xfb00 124-45-235-124 ff
+lowercase \xfb01 124-45-235-24 fi
+#\xfb02 ffi
+#\xfb03 ffl
+lowercase \xfb05 124-45-235-2345 ſt
+lowercase \xfb06 234-45-235-2345 st
+
+
+# Unicode: Cyrillic
+# see above as to why these are here
+# Note Cyrillic characters are not part of UEB
+# These are only there at all to help correct OCR errors
+# Therefore none of the below should backtranslate to Cyrillic
+
+noback lowercase \x0450 45-16-15 ѐ
+noback lowercase \x0451 45-25-15 ё
+noback lowercase \x0457 45-25-24 ї
+noback lowercase \x045c 45-34-13 ќ
+noback lowercase \x04e5 45-346-13456 ў
+noback lowercase \x04ab 45-12346-14 ҫ
+noback lowercase \x04b1 4-25-13456 ұ
+noback lowercase \x04d1 4-346-1 ӑ
+noback lowercase \x04d3 45-25-1 ӓ
+noback uppercase \x04d4 1-6-45-235-15 Ӕ
+noback lowercase \x04d5 1-45-235-15 ӕ
+noback lowercase \x04d7 45-346-15 ӗ
+noback lowercase \x04d9 456-26 ә
+noback lowercase \x04ef 4-36-13456 ӯ
+noback lowercase \x04f1 45-25-13456 ӱ
+
+
+##### End of Unicode
+
+# Uppercase letters
+
+base uppercase \x00c0 \x00e0 Àà
+base uppercase \x00c1 \x00e1 Áá
+base uppercase \x00c2 \x00e2 Ââ
+base uppercase \x00c3 \x00e3 Ãã
+base uppercase \x00c4 \x00e4 Ää
+base uppercase \x00c5 \x00e5 Åå
+base uppercase \x00c6 \x00e6 Ææ
+base uppercase \x00c7 \x00e7 Çç
+base uppercase \x00c8 \x00e8 Èè
+base uppercase \x00c9 \x00e9 Éé
+base uppercase \x00ca \x00ea Êê
+base uppercase \x00cb \x00eb Ëë
+base uppercase \x00cc \x00ec Ìì
+base uppercase \x00cd \x00ed Íí
+base uppercase \x00ce \x00ee Îî
+base uppercase \x00cf \x00ef Ïï
+base uppercase \x00d0 \x00f0 Ðð
+base uppercase \x00d1 \x00f1 Ññ
+base uppercase \x00d2 \x00f2 Òò
+base uppercase \x00d3 \x00f3 Óó
+base uppercase \x00d4 \x00f4 Ôô
+base uppercase \x00d5 \x00f5 Õõ
+base uppercase \x00d6 \x00f6 Öö
+base uppercase \x00d8 \x00f8 Øø
+base uppercase \x00d9 \x00f9 Ùù
+base uppercase \x00da \x00fa Úú
+base uppercase \x00db \x00fb Ûû
+base uppercase \x00dc \x00fc Üü
+base uppercase \x00dd \x00fd Ýý
+base uppercase \x00de \x00fe Þþ
+base uppercase \x0100 \x0101 Āā
+base uppercase \x0102 \x0103 Ăă
+base uppercase \x0106 \x0107 Ćć
+base uppercase \x0108 \x0109 Ĉĉ
+base uppercase \x010c \x010d Čč
+base uppercase \x010e \x010f Ďď
+base uppercase \x0110 \x0111 Đđ
+base uppercase \x0112 \x0113 Ēē
+base uppercase \x0114 \x0115 Ĕĕ
+base uppercase \x011a \x011b Ěě
+base uppercase \x011c \x011d Ĝĝ
+base uppercase \x011e \x011f Ğğ
+base uppercase \x0122 \x0123 Ģģ
+base uppercase \x0124 \x0125 Ĥĥ
+base uppercase \x0126 \x0127 Ħħ
+base uppercase \x0128 \x0129 Ĩĩ
+base uppercase \x012a \x012b Īī
+base uppercase \x012c \x012d Ĭĭ
+base uppercase \x0132 \x0133 IJ ij
+base uppercase \x0134 \x0135 Ĵĵ
+base uppercase \x0136 \x0137 Ķķ
+base uppercase \x0139 \x013a Ĺĺ
+base uppercase \x013b \x013c Ļļ
+base uppercase \x013d \x013e Ľľ
+base uppercase \x0141 \x0142 Łł
+base uppercase \x0143 \x0144 Ńń
+base uppercase \x0145 \x0146 Ņņ
+base uppercase \x0147 \x0148 Ňň
+base uppercase \x014a \x014b Ŋŋ
+base uppercase \x014c \x014d Ōō
+base uppercase \x014e \x014f Ŏŏ
+base uppercase \x0152 \x0153 Œœ
+base uppercase \x0154 \x0155 Ŕŕ
+base uppercase \x0156 \x0157 Ŗŗ
+base uppercase \x0158 \x0159 Řř
+base uppercase \x015a \x015b Śś
+base uppercase \x015c \x015d Ŝŝ
+base uppercase \x015e \x015f Şş
+base uppercase \x0160 \x0161 Šš
+base uppercase \x0162 \x0163 Ţţ
+base uppercase \x0164 \x0165 Ťť
+base uppercase \x0166 \x0167 Ŧŧ
+base uppercase \x0168 \x0169 Ũũ
+base uppercase \x016a \x016b Ūū
+base uppercase \x016c \x016d Ŭŭ
+base uppercase \x016e \x016f Ůů
+base uppercase \x0174 \x0175 Ŵŵ
+base uppercase \x0176 \x0177 Ŷŷ
+base uppercase \x0178 \x00ff Ÿÿ
+base uppercase \x0179 \x017a Źź
+base uppercase \x017d \x017e Žž
+base uppercase \x018f \x0259 Əə
+base uppercase \x018e \x01dd Ǝǝ
+base uppercase \x0197 \x0268 Ɨɨ
+base uppercase \x01b5 \x01b6 Ƶƶ
+base uppercase \x01cd \x01ce Ǎǎ
+base uppercase \x01cf \x01d0 Ǐǐ
+base uppercase \x01d1 \x01d2 Ǒǒ
+base uppercase \x01d3 \x01d4 Ǔǔ
+base uppercase \x01e4 \x01e5 Ǥǥ
+base uppercase \x01e6 \x01e7 Ǧǧ
+base uppercase \x01e8 \x01e9 Ǩǩ
+base uppercase \x01f4 \x01f5 Ǵǵ
+base uppercase \x01f7 \x01bf Ƿƿ
+base uppercase \x01f8 \x01f9 Ǹǹ
+base uppercase \x021c \x021d Ȝȝ
+base uppercase \x021e \x021f Ȟȟ
+base uppercase \x0228 \x0229 Ȩȩ
+base uppercase \x0232 \x0233 Ȳȳ
+base uppercase \x023a \x2c65 Ⱥⱥ
+base uppercase \x023b \x023c Ȼȼ
+base uppercase \x023e \x2c66 Ⱦⱦ
+base uppercase \x0243 \x0180 Ƀƀ
+base uppercase \x0246 \x0247 Ɇɇ
+base uppercase \x0248 \x0249 Ɉɉ
+base uppercase \x024c \x024d Ɍɍ
+base uppercase \x024e \x024f Ɏɏ
+base uppercase \x0391 \x03b1 Αα Alpha
+base uppercase \x0392 \x03b2 Ββ Beta
+base uppercase \x0393 \x03b3 Γγ Gamma
+base uppercase \x0394 \x03b4 Δδ Delta
+base uppercase \x0395 \x03b5 Εε Epsilon
+base uppercase \x0396 \x03b6 Ζζ Zeta
+base uppercase \x0397 \x03b7 Ηη Eta
+base uppercase \x0398 \x03b8 Θθ Theta
+base uppercase \x0399 \x03b9 Ιι Iota
+base uppercase \x039a \x03ba Κκ Kappa
+base uppercase \x039b \x03bb Λλ Lamda
+base uppercase \x039c \x03bc Μμ Mu
+base uppercase \x039d \x03bd Νν Nu
+base uppercase \x039e \x03be Ξξ Xi
+base uppercase \x039f \x03bf Οο Omicron
+base uppercase \x03a0 \x03c0 Ππ Pi
+base uppercase \x03a1 \x03c1 Ρρ Rho
+base uppercase \x03a3 \x03c3 Σσ Sigma
+base uppercase \x03a4 \x03c4 Ττ Tau
+base uppercase \x03a5 \x03c5 Υυ Upsilon
+base uppercase \x03a6 \x03c6 Φφ Phi
+base uppercase \x03a7 \x03c7 Χχ Chi
+base uppercase \x03a8 \x03c8 Ψψ Psi
+base uppercase \x03a9 \x03c9 Ωω Omega
+base uppercase \x1e10 \x1e11 Ḑḑ
+base uppercase \x1e20 \x1e21 Ḡḡ
+base uppercase \x1e26 \x1e27 Ḧḧ
+base uppercase \x1e28 \x1e29 Ḩḩ
+base uppercase \x1e30 \x1e31 Ḱḱ
+base uppercase \x1e3e \x1e3f Ḿḿ
+base uppercase \x1e54 \x1e55 Ṕṕ
+base uppercase \x1e7c \x1e7d Ṽṽ
+base uppercase \x1e80 \x1e81 Ẁẁ
+base uppercase \x1e82 \x1e83 Ẃẃ
+base uppercase \x1e84 \x1e85 Ẅẅ
+base uppercase \x1e8c \x1e8d Ẍẍ
+base uppercase \x1e90 \x1e91 Ẑẑ
+base uppercase \x1e9e \x00df ẞß
+base uppercase \x1ebc \x1ebd Ẽẽ
+base uppercase \x1ef2 \x1ef3 Ỳỳ
+base uppercase \x1ef8 \x1ef9 Ỹỹ
+base uppercase \x2c63 \x1d7d Ᵽᵽ
+base uppercase \xa740 \xa741 Ꝁꝁ
+base uppercase \xa742 \xa743 Ꝃꝃ
+base uppercase \xa750 \xa751 Ꝑꝑ
+base uppercase \xa756 \xa757 Ꝗꝗ
+base uppercase \xa758 \xa759 Ꝙꝙ
+base uppercase \xa75e \xa75f Ꝟꝟ
+base uppercase \xa798 \xa799 Ꞙꞙ
+base uppercase \x0400 \x0450 Ѐѐ
+base uppercase \x0401 \x0451 Ёё
+base uppercase \x0407 \x0457 Її
+base uppercase \x040c \x045c Ќќ
+base uppercase \x040e \x04e5 Ўў
+base uppercase \x04aa \x04ab Ҫҫ
+base uppercase \x04b0 \x04b1 Ұұ
+base uppercase \x04d0 \x04d1 Ӑӑ
+base uppercase \x04d2 \x04d3 Ӓӓ
+base uppercase \x04d6 \x04d7 Ӗӗ
+base uppercase \x04d8 \x04d9 Әә
+base uppercase \x04ee \x04ef Ӯӯ
+base uppercase \x04f0 \x04f1 Ӱӱ
+
+
+# Numeric Symbols
+
+digit 0 356
+digit 1 2
+digit 2 23
+digit 3 25
+digit 4 256
+digit 5 26
+digit 6 235
+digit 7 2356
+digit 8 236
+digit 9 35
+
+litdigit 0 245
+litdigit 1 1
+litdigit 2 12
+litdigit 3 14
+litdigit 4 145
+litdigit 5 15
+litdigit 6 124
+litdigit 7 1245
+litdigit 8 125
+litdigit 9 24
+
+
+# Unicode prefers \x2019 for apostrophe instead of \x0027
+
+endword 'd 3-145
+noback endword \x2019d 3-145
+endword 'll 3-123-123
+noback endword \x2019ll 3-123-123
+endword 'm 3-134
+noback endword \x2019m 3-134
+endword 'n 3-1345
+noback endword \x2019n 3-1345
+endword 're 3-1235-15
+noback endword \x2019re 3-1235-15
+endword 's 3-234
+noback endword \x2019s 3-234
+endword s' 234-3
+noback endword s\x2019 234-3
+endword 't 3-2345
+noback endword \x2019t 3-2345
+endword 've 3-1236-15
+noback endword \x2019ve 3-1236-15
+
+
+# Remove dot 6 from ligatures (æ, œ and ij) when they are lowercase or part of an uppercase word
+
+noback pass2 @6-6-1-6-45-235-15 @6-6-1-45-235-15
+noback pass2 @6-1-6-45-235-15 *
+noback pass2 @1-6-45-235-15 @1-45-235-15
+
+noback pass2 @6-6-135-6-45-235-15 @6-6-135-45-235-15
+noback pass2 @6-135-6-45-235-15 *
+noback pass2 @135-6-45-235-15 @135-45-235-15
+
+noback pass2 @6-6-24-6-45-235-245 @6-6-24-45-235-245
+noback pass2 @6-24-6-45-235-245 *
+noback pass2 @24-6-45-235-245 @24-45-235-245
diff --git a/vendor/liblouis/src/louis/tables/en-ueb-g1.ctb b/vendor/liblouis/src/louis/tables/en-ueb-g1.ctb
new file mode 100644
index 0000000..c95a102
--- /dev/null
+++ b/vendor/liblouis/src/louis/tables/en-ueb-g1.ctb
@@ -0,0 +1,167 @@
+# liblouis: Unified English Braille Code (Grade 1)
+#
+# -----------
+#-name: Unified English braille, grade 1
+#-index-name: English, unified, uncontracted
+#-display-name: Unified English uncontracted braille
+#
+#+language:en
+#+type:literary
+#+contraction:no
+#+grade:1
+#+system:ueb
+#
+# TODO: Please add a reference to official documentation about
+# the implemented braille code. Preferably submit the documents
+# to https://github.com/liblouis/braille-specs.
+# -----------
+#
+# Copyright (C) 2004-2008 ViewPlus Technologies, Inc. www.viewplus.com
+# Copyright (C) 2004-2006 JJB Software, Inc. www.jjb-software.com
+# Copyright (C) 2016 American Printing House for the Blind, Inc. www.aph.org
+# Copyright (C) 2016 Joseph Lee
+# Copyright (C) 2021 RNIB, www.rnib.org.uk
+#
+# This file is part of liblouis.
+#
+# liblouis is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation, either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# liblouis is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with liblouis. If not, see
+# .
+#
+#-maintainer: James Bowden
+#-author: John J. Boyer
+#-author: Mike Gray
+#-author: Joseph Lee
+
+include en-ueb-chardefs.uti UEB specific char defs.
+# some dots are undefined now
+include en-ueb-math.ctb UEB math from common linear format
+
+numsign 3456 number sign, just a dots operand
+numericmodechars .,
+nocontractsign 56
+nonumsign 56
+numericnocontchars abcdefghijABCDEFGHIJ
+
+# A capital ends numeric mode, so clean up extraneous letter indicators between a number
+# and a subsequent capital letter
+noback pass2 _$D[@6-56]$U @6 # handle "1234Card"
+noback pass2 _$D[@6-6-56]$U @6-6 # handle "1234CARD"
+noback pass2 _$D[@256-6-6-56]$U @256-6-6 # handle "1234.CARD"
+noback pass2 _$D[@256-6-56]$U @256-6 # handle "1234.Card"
+
+# Correct order of comma and numeric indicator
+match %a , %# 2-34569 force correct position of numeric indicator
+noback pass2 @3456-2-34569 @2-3456 Clear up extra indicator after the match line
+
+# Correct order of dot and numeric indicator
+match %a . %# 256-34569 force correct position of numeric indicator
+noback pass2 @3456-256-34569 @256-3456 Clear up extra indicator after the match line
+
+# numeric space
+noback correct _$d["\x00a0"]$d "\xE020" # change space to custom symbol representing numeric space
+nofor correct _$d["\xE020"]$d "\x00a0"
+litdigit \xE020 5a # add virtual dot to make distinction with other uses of dot 5
+noback pass2 @5a @5
+nofor pass2 [@3456]$D @3456#1=1 # enter numeric mode when number sign followed by digit is encountered
+nofor pass2 $D *
+nofor pass2 #1=1[@5]$D @5a # when in numeric mode interpret dot 5 as numeric space
+nofor pass2 $a *#1=0 # exit numeric mode when other character than digit or numeric space is encountered
+
+capsletter 6
+begcapsword 6-6
+endcapsword 6-3
+lencapsphrase 3
+begcapsphrase 6-6-6
+endcapsphrase after 6-3
+
+emphclass italic
+emphclass underline
+emphclass bold
+emphclass script
+emphclass transnote
+emphclass trans1
+emphclass trans2
+emphclass trans3
+emphclass trans4
+emphclass trans5
+
+emphletter italic 46-23
+begemphword italic 46-2
+endemphword italic 46-3
+lenemphphrase italic 3
+begemphphrase italic 46-2356
+endemphphrase italic after 46-3
+
+emphletter bold 45-23
+begemphword bold 45-2
+endemphword bold 45-3
+lenemphphrase bold 3
+begemphphrase bold 45-2356
+endemphphrase bold after 45-3
+
+emphletter underline 456-23
+begemphword underline 456-2
+endemphword underline 456-3
+lenemphphrase underline 3
+begemphphrase underline 456-2356
+endemphphrase underline after 456-3
+
+emphletter script 4-23
+begemphword script 4-2
+endemphword script 4-3
+lenemphphrase script 3
+begemphphrase script 4-2356
+endemphphrase script after 4-3
+
+begemph transnote 4-46-126
+endemph transnote 4-46-354
+
+
+emphletter trans1 4-3456-23
+begemphword trans1 4-3456-2
+endemphword trans1 4-3456-3
+lenemphphrase trans1 3
+begemphphrase trans1 4-3456-2356
+endemphphrase trans1 after 4-3456-3
+
+emphletter trans2 45-3456-23
+begemphword trans2 45-3456-2
+endemphword trans2 45-3456-3
+lenemphphrase trans2 3
+begemphphrase trans2 45-3456-2356
+endemphphrase trans2 after 45-3456-3
+
+emphletter trans3 456-3456-23
+begemphword trans3 456-3456-2
+endemphword trans3 456-3456-3
+lenemphphrase trans3 3
+begemphphrase trans3 456-3456-2356
+endemphphrase trans3 after 456-3456-3
+
+emphletter trans4 5-3456-23
+begemphword trans4 5-3456-2
+endemphword trans4 5-3456-3
+lenemphphrase trans4 3
+begemphphrase trans4 5-3456-2356
+endemphphrase trans4 after 5-3456-3
+
+emphletter trans5 46-3456-23
+begemphword trans5 46-3456-2
+endemphword trans5 46-3456-3
+lenemphphrase trans5 3
+begemphphrase trans5 46-3456-2356
+endemphphrase trans5 after 46-3456-3
+
+# display/passthrough for unicode braille
+include braille-patterns.cti
diff --git a/vendor/liblouis/src/louis/tables/en-ueb-math.ctb b/vendor/liblouis/src/louis/tables/en-ueb-math.ctb
new file mode 100644
index 0000000..320607c
--- /dev/null
+++ b/vendor/liblouis/src/louis/tables/en-ueb-math.ctb
@@ -0,0 +1,71 @@
+# liblouis: English (Unified) math definitions
+#
+# Copyright (C) 2016 American Printing House for the Blind, Inc. www.aph.org
+#
+# This file is part of liblouis.
+#
+# liblouis is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation, either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# liblouis is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with liblouis. If not, see
+# .
+
+# Semantic character sequences
+# Prefix characters, only definitions as they should always occur as pairs with other characters.
+
+math \xf400 0
+math \xf401 0
+math \xf402 0
+math \xf403 0
+# Begin and end equations
+replace \xf32e
+replace \xf32f
+# Subscript and superscript
+math \xf320 26-126
+replace \xf401\xf320
+#always \xf402\xf320 345
+math \xf321 35-126
+replace \xf401\xf321
+#always \xf402\xf321 345
+# Underscript and overscript
+math \xf322 46-26-126
+replace \xf401\xf322
+#always \xf402\xf322 345
+math \xf323 46-35-126
+replace \xf401\xf323
+#always \xf402\xf323 345
+# Roots
+math \xf32a 146
+math \xf32b 346
+math \xf32c 146-35-126
+#always \xf403\xf32a 345
+# Fractions
+math \xf500 12356
+math \xf501 23456
+math \xf503 46-34
+# Grouping symbols
+math \xf326 126
+#math \xf327 345
+
+# Protect against incorrect use of escapes or where escape not really needed
+# eg. brackets from mfenced
+replace \xf400
+replace \xf401
+replace \xf402
+replace \xf403
+
+# Corrections
+# Remove grouping from around superscripts and subscripts
+noback pass2 @35-126[$d1-5]@345 @35*
+noback pass2 @26-126[$d1-5]@345 @26*
+# Remove grouping from fractions
+noback pass2 @12356-126[$d1-5]@345-46-34_2 @12356*
+noback pass2 @46-34-126[$d1-5]@345-23456 @46-34*@23456
diff --git a/vendor/liblouis/src/louis/tables/latinLetterDef6Dots.uti b/vendor/liblouis/src/louis/tables/latinLetterDef6Dots.uti
new file mode 100644
index 0000000..9ffefc8
--- /dev/null
+++ b/vendor/liblouis/src/louis/tables/latinLetterDef6Dots.uti
@@ -0,0 +1,78 @@
+# liblouis: sub table for Latin letter definition, 6 dots.
+#
+# Copyright (C) 2012-2014 Mesar Hameed
+#
+# This file is part of liblouis.
+#
+# liblouis is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation, either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# liblouis is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with liblouis. If not, see
+# .
+
+# Latin letters a-z where capitals are defined as equivalent to the lowercase.
+# This table is usually used by 6 dot tables. To distinguish between
+# capitals and lowercase, the language table should make use of the
+# capsletter and capsword opcodes.
+
+lowercase a 1
+lowercase b 12
+lowercase c 14
+lowercase d 145
+lowercase e 15
+lowercase f 124
+lowercase g 1245
+lowercase h 125
+lowercase i 24
+lowercase j 245
+lowercase k 13
+lowercase l 123
+lowercase m 134
+lowercase n 1345
+lowercase o 135
+lowercase p 1234
+lowercase q 12345
+lowercase r 1235
+lowercase s 234
+lowercase t 2345
+lowercase u 136
+lowercase v 1236
+lowercase w 2456
+lowercase x 1346
+lowercase y 13456
+lowercase z 1356
+
+base uppercase A a
+base uppercase B b
+base uppercase C c
+base uppercase D d
+base uppercase E e
+base uppercase F f
+base uppercase G g
+base uppercase H h
+base uppercase I i
+base uppercase J j
+base uppercase K k
+base uppercase L l
+base uppercase M m
+base uppercase N n
+base uppercase O o
+base uppercase P p
+base uppercase Q q
+base uppercase R r
+base uppercase S s
+base uppercase T t
+base uppercase U u
+base uppercase V v
+base uppercase W w
+base uppercase X x
+base uppercase Y y
+base uppercase Z z
diff --git a/vendor/liblouis/src/louis/tables/latinUppercaseComp6.uti b/vendor/liblouis/src/louis/tables/latinUppercaseComp6.uti
new file mode 100644
index 0000000..2736a9f
--- /dev/null
+++ b/vendor/liblouis/src/louis/tables/latinUppercaseComp6.uti
@@ -0,0 +1,78 @@
+# liblouis: comp6 rules for Latin uppercase letters
+#
+# Copyright (C) 2021 Bert Frees
+#
+# This file is part of liblouis.
+#
+# liblouis is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation, either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# liblouis is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with liblouis. If not, see
+# .
+
+# Mark Latin uppercase letters with dot 7 in computer braille
+# mode. Should be used in combination with latinLetterDef6Dots.uti.
+
+comp6 A 17
+comp6 B 127
+comp6 C 147
+comp6 D 1457
+comp6 E 157
+comp6 F 1247
+comp6 G 12457
+comp6 H 1257
+comp6 I 247
+comp6 J 2457
+comp6 K 137
+comp6 L 1237
+comp6 M 1347
+comp6 N 13457
+comp6 O 1357
+comp6 P 12347
+comp6 Q 123457
+comp6 R 12357
+comp6 S 2347
+comp6 T 23457
+comp6 U 1367
+comp6 V 12367
+comp6 W 24567
+comp6 X 13467
+comp6 Y 134567
+comp6 Z 13567
+
+# Back-translate uppercase letters in computer braille mode.
+
+nofor always A 17
+nofor always B 127
+nofor always C 147
+nofor always D 1457
+nofor always E 157
+nofor always F 1247
+nofor always G 12457
+nofor always H 1257
+nofor always I 247
+nofor always J 2457
+nofor always K 137
+nofor always L 1237
+nofor always M 1347
+nofor always N 13457
+nofor always O 1357
+nofor always P 12347
+nofor always Q 123457
+nofor always R 12357
+nofor always S 2347
+nofor always T 23457
+nofor always U 1367
+nofor always V 12367
+nofor always W 24567
+nofor always X 13467
+nofor always Y 134567
+nofor always Z 13567
diff --git a/vendor/liblouis/src/louis/tables/spaces.uti b/vendor/liblouis/src/louis/tables/spaces.uti
new file mode 100644
index 0000000..e72b674
--- /dev/null
+++ b/vendor/liblouis/src/louis/tables/spaces.uti
@@ -0,0 +1,62 @@
+#
+# Copyright (C) 2010 by JJB Software, Inc. www.jjb-software.com
+#
+# This file is part of liblouis.
+#
+# liblouis is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation, either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# liblouis is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with liblouis. If not, see
+# .
+
+# Previously, these definitions were hardcoded in the liblouis library
+# itself. Now they are migrated to an external table which can be
+# included by other tables. They are necessary for the proper operation
+# of liblouis or liblouisutdml.
+
+# This table also defines all the space characters to be empty braille
+# cells.
+
+space \s 0 SPACE
+
+sign \x0000 0 NULL
+space \x0009 0 CHARACTER TABULATION
+space \x000a 0 LINE FEED (LF)
+space \x000b 0 LINE TABULATION
+space \x000c 0 FORM FEED (FF)
+space \x000d 0 CARRIAGE RETURN (CR)
+space \x00a0 0 NO-BREAK SPACE
+space \x2000 0 EN QUAD
+space \x2001 0 EM QUAD
+space \x2002 0 EN SPACE
+space \x2003 0 EM SPACE
+space \x2004 0 THREE-PER-EM SPACE
+space \x2005 0 FOUR-PER-EM SPACE
+space \x2006 0 SIX-PER-EM SPACE
+space \x2007 0 FIGURE SPACE
+space \x2008 0 PUNCTUATION SPACE
+space \x2009 0 THIN SPACE
+space \x200a 0 HAIR SPACE
+space \x200b 0 ZERO WIDTH SPACE
+space \x2028 0 LINE SEPARATOR
+space \x2029 0 PARAGRAPH SEPARATOR
+space \x202f 0 NARROW NO-BREAK SPACE
+space \x205f 0 MEDIUM MATHEMATICAL SPACE
+space \x2060 0 WORD JOINER
+space \x2800 0 BRAILLE PATTERN BLANK
+space \xfeff 0 ZERO WIDTH NO-BREAK SPACE (also Unicode BOM)
+
+# replace \x200b #ZERO WIDTH SPACE
+noback correct "\x200b" ""
+
+replace \x2060 #WORD JOINER
+replace \xfeff #ZERO WIDTH NO-BREAK SPACE (also Unicode BOM)
+
diff --git a/vendor/liblouis/src/louis/tables/text_nabcc.dis b/vendor/liblouis/src/louis/tables/text_nabcc.dis
new file mode 100644
index 0000000..dde2890
--- /dev/null
+++ b/vendor/liblouis/src/louis/tables/text_nabcc.dis
@@ -0,0 +1,426 @@
+# liblouis: text.nabcc.dis
+#
+# Based on the braille contraction modules in BRLTTY
+#
+# Copyright (C) 1995-2004 by The BRLTTY Team
+# Copyright (C) 2004 ViewPlus Technologies, Inc., www.viewplustech.com
+# Copyright (C) 2004 Computers to Help People, Inc., www.chpi.org
+
+# This file is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with this file; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+# liblouis comes with ABSOLUTELY NO WARRANTY.
+
+# This is a description of the default text translation table used by BRLTTY.
+# It's based on the North American Braille Computer Code, but defines the full
+# Latin1 (ISO-8859-1) character set.
+
+# The 95 printable characters of the standard 7-bit US-ASCII character set
+# (32-126) are identical to their representations within the North American
+# Braille Computer Code (these are the only characters which the NABCC actually
+# defines). Characters from literary braille, symbols from The Nemeth Braille
+# Code for Mathematics and Science Notation, and a bit of human imagination
+# have all been combined to create an easy-to-remember, one-to-one mapping
+# between each character and its braille counterpart. All possible combinations
+# involving only the original 6 braille dots are used, but that only allows for
+# 64 out of the required 95 character representations. The presence or absence
+# of dot 7 is used to differentiate between pairs of characters which either
+# are very closely related in meaning or, in a few cases where a more intuitive
+# reason couldn't be found, have a very close logical relationship within the
+# US-ASCII code. Dot 8 is used for control characters and accented characters.
+
+# This table is synchronized with Text/en-nabcc.ttb table from the BRLTTY
+# project, except the re-added no-break space mapping.
+
+# The space and the 26 lowercase letters (a-z) are the same as in literary
+# braille:
+
+# Hex Dots Dec Char Description
+display \x0020 0 # 32 SPACE
+display \x0061 1 # 97 a LATIN SMALL LETTER A
+display \x0062 12 # 98 b LATIN SMALL LETTER B
+display \x0063 14 # 99 c LATIN SMALL LETTER C
+display \x0064 145 # 100 d LATIN SMALL LETTER D
+display \x0065 15 # 101 e LATIN SMALL LETTER E
+display \x0066 124 # 102 f LATIN SMALL LETTER F
+display \x0067 1245 # 103 g LATIN SMALL LETTER G
+display \x0068 125 # 104 h LATIN SMALL LETTER H
+display \x0069 24 # 105 i LATIN SMALL LETTER I
+display \x006a 245 # 106 j LATIN SMALL LETTER J
+display \x006b 13 # 107 k LATIN SMALL LETTER K
+display \x006c 123 # 108 l LATIN SMALL LETTER L
+display \x006d 134 # 109 m LATIN SMALL LETTER M
+display \x006e 1345 # 110 n LATIN SMALL LETTER N
+display \x006f 135 # 111 o LATIN SMALL LETTER O
+display \x0070 1234 # 112 p LATIN SMALL LETTER P
+display \x0071 12345 # 113 q LATIN SMALL LETTER Q
+display \x0072 1235 # 114 r LATIN SMALL LETTER R
+display \x0073 234 # 115 s LATIN SMALL LETTER S
+display \x0074 2345 # 116 t LATIN SMALL LETTER T
+display \x0075 136 # 117 u LATIN SMALL LETTER U
+display \x0076 1236 # 118 v LATIN SMALL LETTER V
+display \x0077 2456 # 119 w LATIN SMALL LETTER W
+display \x0078 1346 # 120 x LATIN SMALL LETTER X
+display \x0079 13456 # 121 y LATIN SMALL LETTER Y
+display \x007a 1356 # 122 z LATIN SMALL LETTER Z
+
+# The 26 uppercase letters A-Z) are the same as their lowercase counterparts
+# except that dot7 is added:
+
+# Hex Dots Dec Char Description
+display \x0041 17 # 65 A LATIN CAPITAL LETTER A
+display \x0042 127 # 66 B LATIN CAPITAL LETTER B
+display \x0043 147 # 67 C LATIN CAPITAL LETTER C
+display \x0044 1457 # 68 D LATIN CAPITAL LETTER D
+display \x0045 157 # 69 E LATIN CAPITAL LETTER E
+display \x0046 1247 # 70 F LATIN CAPITAL LETTER F
+display \x0047 12457 # 71 G LATIN CAPITAL LETTER G
+display \x0048 1257 # 72 H LATIN CAPITAL LETTER H
+display \x0049 247 # 73 I LATIN CAPITAL LETTER I
+display \x004a 2457 # 74 J LATIN CAPITAL LETTER J
+display \x004b 137 # 75 K LATIN CAPITAL LETTER K
+display \x004c 1237 # 76 L LATIN CAPITAL LETTER L
+display \x004d 1347 # 77 M LATIN CAPITAL LETTER M
+display \x004e 13457 # 78 N LATIN CAPITAL LETTER N
+display \x004f 1357 # 79 O LATIN CAPITAL LETTER O
+display \x0050 12347 # 80 P LATIN CAPITAL LETTER P
+display \x0051 123457 # 81 Q LATIN CAPITAL LETTER Q
+display \x0052 12357 # 82 R LATIN CAPITAL LETTER R
+display \x0053 2347 # 83 S LATIN CAPITAL LETTER S
+display \x0054 23457 # 84 T LATIN CAPITAL LETTER T
+display \x0055 1367 # 85 U LATIN CAPITAL LETTER U
+display \x0056 12367 # 86 V LATIN CAPITAL LETTER V
+display \x0057 24567 # 87 W LATIN CAPITAL LETTER W
+display \x0058 13467 # 88 X LATIN CAPITAL LETTER X
+display \x0059 134567 # 89 Y LATIN CAPITAL LETTER Y
+display \x005a 13567 # 90 Z LATIN CAPITAL LETTER Z
+
+# The 10 decimal digits 0-9) are the same as in the Nemeth Code:
+
+# Hex Dots Dec Char Description
+display \x0030 356 # 48 0 DIGIT ZERO
+display \x0031 2 # 49 1 DIGIT ONE
+display \x0032 23 # 50 2 DIGIT TWO
+display \x0033 25 # 51 3 DIGIT THREE
+display \x0034 256 # 52 4 DIGIT FOUR
+display \x0035 26 # 53 5 DIGIT FIVE
+display \x0036 235 # 54 6 DIGIT SIX
+display \x0037 2356 # 55 7 DIGIT SEVEN
+display \x0038 236 # 56 8 DIGIT EIGHT
+display \x0039 35 # 57 9 DIGIT NINE
+
+# Common symbols used within mathematical expressions by popular computer
+# programming languages are the same as in the Nemeth Code:
+
+# Hex Dots Dec Char Description
+display \x002e 46 # 46 . FULL STOP
+display \x002b 346 # 43 + PLUS SIGN
+display \x002d 36 # 45 - HYPHEN-MINUS
+display \x002a 16 # 42 * ASTERISK
+display \x002f 34 # 47 / SOLIDUS
+display \x0028 12356 # 40 ( LEFT PARENTHESIS
+display \x0029 23456 # 41 ) RIGHT PARENTHESIS
+
+# With all of these major considerations having been taken into account,
+# convenient representations were still available, and are used, for some of
+# the remaining characters:
+
+# Hex Dots Dec Char Description
+display \x0026 12346 # 38 & AMPERSAND
+display \x0023 3456 # 35 # NUMBER SIGN
+
+# The remaining characters are what they are. Dot 7 isn't used either within
+# the number block (32-63) or, with the exception of the DEL control character
+# (127), within the lowercase block (96-127). With the exception of the
+# underscore (95), dot 7 is used for every character within the uppercase block
+# (64-95). Adding dot 7 to any character within the lowercase block (96-127)
+# yields its corresponding character within the uppercase block (64-95) except
+# that removing dot 7 from the DEL control character yields the underscore.
+
+# Hex Dots Dec Char Description
+display \x002c 6 # 44 , COMMA
+display \x003b 56 # 59 ; SEMICOLON
+display \x003a 156 # 58 : COLON
+display \x0021 2346 # 33 ! EXCLAMATION MARK
+display \x003f 1456 # 63 ? QUESTION MARK
+display \x0022 5 # 34 " QUOTATION MARK
+display \x0027 3 # 39 ' APOSTROPHE
+display \x0060 4 # 96 ` GRAVE ACCENT
+display \x005e 457 # 94 ^ CIRCUMFLEX ACCENT
+display \x007e 45 # 126 ~ TILDE
+display \x005b 2467 # 91 [ LEFT SQUARE BRACKET
+display \x005d 124567 # 93 ] RIGHT SQUARE BRACKET
+display \x007b 246 # 123 { LEFT CURLY BRACKET
+display \x007d 12456 # 125 } RIGHT CURLY BRACKET
+display \x003d 123456 # 61 = EQUALS SIGN
+display \x003c 126 # 60 < LESS-THAN SIGN
+display \x003e 345 # 62 > GREATER-THAN SIGN
+display \x0024 1246 # 36 $ DOLLAR SIGN
+display \x0025 146 # 37 % PERCENT SIGN
+display \x0040 47 # 64 @ COMMERCIAL AT
+display \x007c 1256 # 124 | VERTICAL LINE
+display \x005c 12567 # 92 \ REVERSE SOLIDUS
+display \x005f 456 # 95 _ LOW LINE
+
+# The DEL control character
+# Hex Dots Dec Char Description
+display \x007f 4567 # 127 ^? DELETE
+
+# Each of the characters within the basic control character block (0-31) is the
+# same as its corresponding character within both the uppercase block (64-95)
+# and the lowercase block (96-127) except that dots 7 and 8 are both used.
+
+# Hex Dots Dec Char Description
+display \x0000 478 # 0 ^@ NULL
+display \x0001 178 # 1 ^A START OF HEADING
+display \x0002 1278 # 2 ^B START OF TEXT
+display \x0003 1478 # 3 ^C END OF TEXT
+display \x0004 14578 # 4 ^D END OF TRANSMISSION
+display \x0005 1578 # 5 ^E ENQUIRY
+display \x0006 12478 # 6 ^F ACKNOWLEDGE
+display \x0007 124578 # 7 ^G BELL
+display \x0008 12578 # 8 ^H BACKSPACE
+display \x0009 2478 # 9 ^I HORIZONTAL TABULATION
+display \x000a 24578 # 10 ^J LINE FEED
+display \x000b 1378 # 11 ^K VERTICAL TABULATION
+display \x000c 12378 # 12 ^L FORM FEED
+display \x000d 13478 # 13 ^M CARRIAGE RETURN
+display \x000e 134578 # 14 ^N SHIFT OUT
+display \x000f 13578 # 15 ^O SHIFT IN
+display \x0010 123478 # 16 ^P DATA LINK ESCAPE
+display \x0011 1234578 # 17 ^Q DEVICE CONTROL ONE
+display \x0012 123578 # 18 ^R DEVICE CONTROL TWO
+display \x0013 23478 # 19 ^S DEVICE CONTROL THREE
+display \x0014 234578 # 20 ^T DEVICE CONTROL FOUR
+display \x0015 13678 # 21 ^U NEGATIVE ACKNOWLEDGE
+display \x0016 123678 # 22 ^V SYNCHRONOUS IDLE
+display \x0017 245678 # 23 ^W END OF TRANSMISSION BLOCK
+display \x0018 134678 # 24 ^X CANCEL
+display \x0019 1345678 # 25 ^Y END OF MEDIUM
+display \x001a 135678 # 26 ^Z SUBSTITUTE
+display \x001b 24678 # 27 ^[ ESCAPE
+display \x001c 125678 # 28 ^\ FILE SEPARATOR
+display \x001d 1245678 # 29 ^] GROUP SEPARATOR
+display \x001e 4578 # 30 ^^ RECORD SEPARATOR
+display \x001f 45678 # 31 ^_ UNIT SEPARATOR
+
+# Each of the characters within the extended control character block (128-159)
+# is the same as its corresponding character within the basic control character
+# block (0-31) except that only dot 8 is used.
+
+# Hex Dots Dec Char Description
+display \x0080 48 # 128 ~@
+display \x0081 18 # 129 ~A
+display \x0082 128 # 130 ~B BREAK PERMITTED HERE
+display \x0083 148 # 131 ~C NO BREAK HERE
+display \x0084 1458 # 132 ~D
+display \x0085 158 # 133 ~E NEXT LINE
+display \x0086 1248 # 134 ~F START OF SELECTED AREA
+display \x0087 12458 # 135 ~G END OF SELECTED AREA
+display \x0088 1258 # 136 ~H CHARACTER TABULATION SET
+display \x0089 248 # 137 ~I CHARACTER TABULATION WITH JUSTIFICATION
+display \x008a 2458 # 138 ~J LINE TABULATION SET
+display \x008b 138 # 139 ~K PARTIAL LINE DOWN
+display \x008c 1238 # 140 ~L PARTIAL LINE UP
+display \x008d 1348 # 141 ~M REVERSE LINE FEED
+display \x008e 13458 # 142 ~N SINGLE SHIFT TWO
+display \x008f 1358 # 143 ~O SINGLE SHIFT THREE
+display \x0090 12348 # 144 ~P DEVICE CONTROL STRING
+display \x0091 123458 # 145 ~Q PRIVATE USE ONE
+display \x0092 12358 # 146 ~R PRIVATE USE TWO
+display \x0093 2348 # 147 ~S SET TRANSMIT STATE
+display \x0094 23458 # 148 ~T CANCEL CHARACTER
+display \x0095 1368 # 149 ~U MESSAGE WAITING
+display \x0096 12368 # 150 ~V START OF GUARDED AREA
+display \x0097 24568 # 151 ~W END OF GUARDED AREA
+display \x0098 13468 # 152 ~X START OF STRING
+display \x0099 134568 # 153 ~Y
+display \x009a 13568 # 154 ~Z SINGLE CHARACTER INTRODUCER
+display \x009b 2468 # 155 ~[ CONTROL SEQUENCE INTRODUCER
+display \x009c 12568 # 156 ~\ STRING TERMINATOR
+display \x009d 124568 # 157 ~] OPERATING SYSTEM COMMAND
+display \x009e 458 # 158 ~^ PRIVACY MESSAGE
+display \x009f 4568 # 159 ~_ APPLICATION PROGRAM COMMAND
+
+
+# Representations for the uppercase accented letters are drawn from the
+# remaining combinations which use both dots 7 and 8. The representation for a
+# lowercase accented letter is the same as its uppercase counterpart except
+# that dot 7 isn't used. This scheme retains the use of dot 7 as the modifier
+# for a capitalized letter. The only exception to these rules is that, due to
+# the nature of the Latin 1 character set, the German lowercase double-s is
+# treated as though it were an uppercase y-dieresis neither has an uppercase
+# definition). These representations have been gathered, as much as possible,
+# into logical groupings.
+
+# The 5 letters with a circumflex accent (^) use the [1-5] dot combinations:
+
+# Hex Dots Dec Char Description
+display \x00c2 278 # 194 Â LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+display \x00ca 2378 # 202 Ê LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+display \x00ce 2578 # 206 Î LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+display \x00d4 25678 # 212 Ô LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+display \x00db 2678 # 219 Û LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+display \x00e2 28 # 226 â LATIN SMALL LETTER A WITH CIRCUMFLEX
+display \x00ea 238 # 234 ê LATIN SMALL LETTER E WITH CIRCUMFLEX
+display \x00ee 258 # 238 î LATIN SMALL LETTER I WITH CIRCUMFLEX
+display \x00f4 2568 # 244 ô LATIN SMALL LETTER O WITH CIRCUMFLEX
+display \x00fb 268 # 251 û LATIN SMALL LETTER U WITH CIRCUMFLEX
+
+# The 5 letters with a grave accent (`) use the [6-0] dot combinations:
+
+# Hex Dots Dec Char Description
+display \x00c0 23578 # 192 À LATIN CAPITAL LETTER A WITH GRAVE
+display \x00c8 235678 # 200 È LATIN CAPITAL LETTER E WITH GRAVE
+display \x00cc 23678 # 204 Ì LATIN CAPITAL LETTER I WITH GRAVE
+display \x00d2 3578 # 210 Ò LATIN CAPITAL LETTER O WITH GRAVE
+display \x00d9 35678 # 217 Ù LATIN CAPITAL LETTER U WITH GRAVE
+display \x00e0 2358 # 224 à LATIN SMALL LETTER A WITH GRAVE
+display \x00e8 23568 # 232 è LATIN SMALL LETTER E WITH GRAVE
+display \x00ec 2368 # 236 ì LATIN SMALL LETTER I WITH GRAVE
+display \x00f2 358 # 242 ò LATIN SMALL LETTER O WITH GRAVE
+display \x00f9 3568 # 249 ù LATIN SMALL LETTER U WITH GRAVE
+
+# The 6 letters with an acute accent (´) use the [a-f] dot combinations with
+# dots 6 and 8 added:
+
+# Hex Dots Dec Char Description
+display \x00c1 1678 # 193 Á LATIN CAPITAL LETTER A WITH ACUTE
+display \x00c9 12678 # 201 É LATIN CAPITAL LETTER E WITH ACUTE
+display \x00cd 14678 # 205 Í LATIN CAPITAL LETTER I WITH ACUTE
+display \x00d3 145678 # 211 Ó LATIN CAPITAL LETTER O WITH ACUTE
+display \x00da 15678 # 218 Ú LATIN CAPITAL LETTER U WITH ACUTE
+display \x00dd 124678 # 221 Ý LATIN CAPITAL LETTER Y WITH ACUTE
+display \x00e1 168 # 225 á LATIN SMALL LETTER A WITH ACUTE
+display \x00e9 1268 # 233 é LATIN SMALL LETTER E WITH ACUTE
+display \x00ed 1468 # 237 í LATIN SMALL LETTER I WITH ACUTE
+display \x00f3 14568 # 243 ó LATIN SMALL LETTER O WITH ACUTE
+display \x00fa 1568 # 250 ú LATIN SMALL LETTER U WITH ACUTE
+display \x00fd 12468 # 253 ý LATIN SMALL LETTER Y WITH ACUTE
+
+# The 6 letters with a dieresis accent (¨) use the [f-j] dot combinations with
+# dots 3 and 6 added, and the number sign (because it fits the sequence
+# reasonably well):
+
+# Hex Dots Dec Char Description
+display \x00c4 1234678 # 196 Ä LATIN CAPITAL LETTER A WITH DIAERESIS
+display \x00cb 12345678 # 203 Ë LATIN CAPITAL LETTER E WITH DIAERESIS
+display \x00cf 1235678 # 207 Ï LATIN CAPITAL LETTER I WITH DIAERESIS
+display \x00d6 234678 # 214 Ö LATIN CAPITAL LETTER O WITH DIAERESIS
+display \x00dc 2345678 # 220 Ü LATIN CAPITAL LETTER U WITH DIAERESIS
+display \x00e4 123468 # 228 ä LATIN SMALL LETTER A WITH DIAERESIS
+display \x00eb 1234568 # 235 ë LATIN SMALL LETTER E WITH DIAERESIS
+display \x00ef 123568 # 239 ï LATIN SMALL LETTER I WITH DIAERESIS
+display \x00f6 23468 # 246 ö LATIN SMALL LETTER O WITH DIAERESIS
+display \x00fc 234568 # 252 ü LATIN SMALL LETTER U WITH DIAERESIS
+display \x00ff 34568 # 255 ÿ LATIN SMALL LETTER Y WITH DIAERESIS
+
+# There is no uppercase y-dieresis in the Latin1 character set. The German
+# lowercase double-s, which also doesn't have an uppercase counterpart in the
+# Latin1 character set, uses its representation:
+
+# Hex Dots Dec Char Description
+display \x00df 345678 # 223 ß LATIN SMALL LETTER SHARP S
+
+# The remaining accented letters are:
+
+# Hex Dots Dec Char Description
+display \x00c3 578 # 195 Ã LATIN CAPITAL LETTER A WITH TILDE
+display \x00d1 4678 # 209 Ñ LATIN CAPITAL LETTER N WITH TILDE
+display \x00d5 5678 # 213 Õ LATIN CAPITAL LETTER O WITH TILDE
+display \x00c5 34578 # 197 Å LATIN CAPITAL LETTER A WITH RING ABOVE
+display \x00c7 34678 # 199 Ç LATIN CAPITAL LETTER C WITH CEDILLA
+display \x00d8 3478 # 216 Ø LATIN CAPITAL LETTER O WITH STROKE
+display \x00c6 378 # 198 Æ LATIN CAPITAL LETTER AE
+display \x00d0 678 # 208 Ð LATIN CAPITAL LETTER ETH
+display \x00de 3678 # 222 Þ LATIN CAPITAL LETTER THORN
+display \x00e3 58 # 227 ã LATIN SMALL LETTER A WITH TILDE
+display \x00f1 468 # 241 ñ LATIN SMALL LETTER N WITH TILDE
+display \x00f5 568 # 245 õ LATIN SMALL LETTER O WITH TILDE
+display \x00e5 3458 # 229 å LATIN SMALL LETTER A WITH RING ABOVE
+display \x00e7 3468 # 231 ç LATIN SMALL LETTER C WITH CEDILLA
+display \x00f8 348 # 248 ø LATIN SMALL LETTER O WITH STROKE
+display \x00e6 38 # 230 æ LATIN SMALL LETTER AE
+display \x00f0 68 # 240 ð LATIN SMALL LETTER ETH
+display \x00fe 368 # 254 þ LATIN SMALL LETTER THORN
+
+# Some characters are the same as other characters which they resemble but with
+# dot 7 added:
+
+# Hex Dots Dec Char Description
+display \x00ad 367 # 173 SOFT HYPHEN
+display \x00ab 1267 # 171 « LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+display \x00bb 3457 # 187 » RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+display \x00a6 1567 # 166 ¦ BROKEN BAR
+display \x00b9 27 # 185 ¹ SUPERSCRIPT ONE
+display \x00b2 237 # 178 ² SUPERSCRIPT TWO
+display \x00b3 257 # 179 ³ SUPERSCRIPT THREE
+display \x00b1 3467 # 177 ± PLUS-MINUS SIGN
+display \x00d7 167 # 215 × MULTIPLICATION SIGN
+display \x00f7 347 # 247 ÷ DIVISION SIGN
+display \x00b7 467 # 183 · MIDDLE DOT
+display \x00a1 23467 # 161 ¡ INVERTED EXCLAMATION MARK
+display \x00bf 14567 # 191 ¿ INVERTED QUESTION MARK
+display \x00a2 12467 # 162 ¢ CENT SIGN
+display \x00a3 34567 # 163 £ POUND SIGN
+
+# A few more characters follow this same convention but their relationships
+# to their base characters is a bit obscure:
+
+# Hex Dots Dec Char Description
+display \x00a4 1467 # 164 ¤ CURRENCY SIGN
+display \x00a5 123467 # 165 ¥ YEN SIGN
+
+# Some characters are represented by the first letters of their names lowered
+# by one row of dots:
+
+# Hex Dots Dec Char Description
+display \x00ac 2567 # 172 ¬ NOT SIGN
+display \x00b6 2357 # 182 ¶ PILCROW SIGN
+display \x00a9 23567 # 169 © COPYRIGHT SIGN
+display \x00ae 2367 # 174 ® REGISTERED SIGN
+display \x00a7 357 # 167 § SECTION SIGN
+display \x00b0 3567 # 176 ° DEGREE SIGN
+
+# The three fraction characters use combinations of dots 1 and 4 (which
+# progress from left to right as the value of the fraction increases) together
+# with dots 2,3,5,6,7:
+
+# Hex Dots Dec Char Description
+display \x00bc 123567 # 188 ¼ VULGAR FRACTION ONE QUARTER
+display \x00bd 1234567 # 189 ½ VULGAR FRACTION ONE HALF
+display \x00be 234567 # 190 ¾ VULGAR FRACTION THREE QUARTERS
+
+# Each of the three extended accent characters is the same as its conventional
+# compose character but with dot7 added:
+
+# Hex Dots Dec Char Description
+display \x00b4 37 # 180 ´ ACUTE ACCENT
+display \x00b8 67 # 184 ¸ CEDILLA
+display \x00a8 57 # 168 ¨ DIAERESIS
+
+# The two gender symbols are:
+
+# Hex Dots Dec Char Description
+display \x00ba 7 # 186 º MASCULINE ORDINAL INDICATOR
+display \x00aa 8 # 170 ª FEMININE ORDINAL INDICATOR
+
+# The three remaining characters are:
+
+# Hex Dots Dec Char Description
+display \x00af 267 # 175 ¯ MACRON
+display \x00b5 567 # 181 µ MICRO SIGN
+display \x00a0 78 # 160 NO-BREAK SPACE
+
+# The nonbreaking space is dots 7 and 8 because this presents a sequence of
+# nonbreaking spaces as a smooth low line segment.
diff --git a/vendor/liblouis/src/louis/tables/unicode.dis b/vendor/liblouis/src/louis/tables/unicode.dis
new file mode 100644
index 0000000..405ef89
--- /dev/null
+++ b/vendor/liblouis/src/louis/tables/unicode.dis
@@ -0,0 +1,278 @@
+# This file will produce Unicode Braille output.
+# Use it as the first file in a table list.
+#
+# Copyright (C) 2010 JJB Software, Inc. www.jjb-software.com
+#
+# This file is part of liblouis.
+#
+# liblouis is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation, either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# liblouis is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with liblouis. If not, see
+# .
+
+display \x2800 0
+display \x2801 1
+display \x2802 2
+display \x2803 12
+display \x2804 3
+display \x2805 13
+display \x2806 23
+display \x2807 123
+display \x2808 4
+display \x2809 14
+display \x280A 24
+display \x280B 124
+display \x280C 34
+display \x280D 134
+display \x280E 234
+display \x280F 1234
+display \x2810 5
+display \x2811 15
+display \x2812 25
+display \x2813 125
+display \x2814 35
+display \x2815 135
+display \x2816 235
+display \x2817 1235
+display \x2818 45
+display \x2819 145
+display \x281A 245
+display \x281B 1245
+display \x281C 345
+display \x281D 1345
+display \x281E 2345
+display \x281F 12345
+display \x2820 6
+display \x2821 16
+display \x2822 26
+display \x2823 126
+display \x2824 36
+display \x2825 136
+display \x2826 236
+display \x2827 1236
+display \x2828 46
+display \x2829 146
+display \x282A 246
+display \x282B 1246
+display \x282C 346
+display \x282D 1346
+display \x282E 2346
+display \x282F 12346
+display \x2830 56
+display \x2831 156
+display \x2832 256
+display \x2833 1256
+display \x2834 356
+display \x2835 1356
+display \x2836 2356
+display \x2837 12356
+display \x2838 456
+display \x2839 1456
+display \x283A 2456
+display \x283B 12456
+display \x283C 3456
+display \x283D 13456
+display \x283E 23456
+display \x283F 123456
+display \x2840 7
+display \x2841 17
+display \x2842 27
+display \x2843 127
+display \x2844 37
+display \x2845 137
+display \x2846 237
+display \x2847 1237
+display \x2848 47
+display \x2849 147
+display \x284A 247
+display \x284B 1247
+display \x284C 347
+display \x284D 1347
+display \x284E 2347
+display \x284F 12347
+display \x2850 57
+display \x2851 157
+display \x2852 257
+display \x2853 1257
+display \x2854 357
+display \x2855 1357
+display \x2856 2357
+display \x2857 12357
+display \x2858 457
+display \x2859 1457
+display \x285A 2457
+display \x285B 12457
+display \x285C 3457
+display \x285D 13457
+display \x285E 23457
+display \x285F 123457
+display \x2860 67
+display \x2861 167
+display \x2862 267
+display \x2863 1267
+display \x2864 367
+display \x2865 1367
+display \x2866 2367
+display \x2867 12367
+display \x2868 467
+display \x2869 1467
+display \x286A 2467
+display \x286B 12467
+display \x286C 3467
+display \x286D 13467
+display \x286E 23467
+display \x286F 123467
+display \x2870 567
+display \x2871 1567
+display \x2872 2567
+display \x2873 12567
+display \x2874 3567
+display \x2875 13567
+display \x2876 23567
+display \x2877 123567
+display \x2878 4567
+display \x2879 14567
+display \x287A 24567
+display \x287B 124567
+display \x287C 34567
+display \x287D 134567
+display \x287E 234567
+display \x287F 1234567
+display \x2880 8
+display \x2881 18
+display \x2882 28
+display \x2883 128
+display \x2884 38
+display \x2885 138
+display \x2886 238
+display \x2887 1238
+display \x2888 48
+display \x2889 148
+display \x288A 248
+display \x288B 1248
+display \x288C 348
+display \x288D 1348
+display \x288E 2348
+display \x288F 12348
+display \x2890 58
+display \x2891 158
+display \x2892 258
+display \x2893 1258
+display \x2894 358
+display \x2895 1358
+display \x2896 2358
+display \x2897 12358
+display \x2898 458
+display \x2899 1458
+display \x289A 2458
+display \x289B 12458
+display \x289C 3458
+display \x289D 13458
+display \x289E 23458
+display \x289F 123458
+display \x28A0 68
+display \x28A1 168
+display \x28A2 268
+display \x28A3 1268
+display \x28A4 368
+display \x28A5 1368
+display \x28A6 2368
+display \x28A7 12368
+display \x28A8 468
+display \x28A9 1468
+display \x28AA 2468
+display \x28AB 12468
+display \x28AC 3468
+display \x28AD 13468
+display \x28AE 23468
+display \x28AF 123468
+display \x28B0 568
+display \x28B1 1568
+display \x28B2 2568
+display \x28B3 12568
+display \x28B4 3568
+display \x28B5 13568
+display \x28B6 23568
+display \x28B7 123568
+display \x28B8 4568
+display \x28B9 14568
+display \x28BA 24568
+display \x28BB 124568
+display \x28BC 34568
+display \x28BD 134568
+display \x28BE 234568
+display \x28BF 1234568
+display \x28C0 78
+display \x28C1 178
+display \x28C2 278
+display \x28C3 1278
+display \x28C4 378
+display \x28C5 1378
+display \x28C6 2378
+display \x28C7 12378
+display \x28C8 478
+display \x28C9 1478
+display \x28CA 2478
+display \x28CB 12478
+display \x28CC 3478
+display \x28CD 13478
+display \x28CE 23478
+display \x28CF 123478
+display \x28D0 578
+display \x28D1 1578
+display \x28D2 2578
+display \x28D3 12578
+display \x28D4 3578
+display \x28D5 13578
+display \x28D6 23578
+display \x28D7 123578
+display \x28D8 4578
+display \x28D9 14578
+display \x28DA 24578
+display \x28DB 124578
+display \x28DC 34578
+display \x28DD 134578
+display \x28DE 234578
+display \x28DF 1234578
+display \x28E0 678
+display \x28E1 1678
+display \x28E2 2678
+display \x28E3 12678
+display \x28E4 3678
+display \x28E5 13678
+display \x28E6 23678
+display \x28E7 123678
+display \x28E8 4678
+display \x28E9 14678
+display \x28EA 24678
+display \x28EB 124678
+display \x28EC 34678
+display \x28ED 134678
+display \x28EE 234678
+display \x28EF 1234678
+display \x28F0 5678
+display \x28F1 15678
+display \x28F2 25678
+display \x28F3 125678
+display \x28F4 35678
+display \x28F5 135678
+display \x28F6 235678
+display \x28F7 1235678
+display \x28F8 45678
+display \x28F9 145678
+display \x28FA 245678
+display \x28FB 1245678
+display \x28FC 345678
+display \x28FD 1345678
+display \x28FE 2345678
+display \x28FF 12345678
+