uEdition 2.0.0a1__tar.gz → 2.0.0b1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of uEdition might be problematic. Click here for more details.
- {uedition-2.0.0a1 → uedition-2.0.0b1}/PKG-INFO +5 -2
- uedition-2.0.0b1/docs/en/index.md +56 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/pyproject.toml +5 -3
- uedition-2.0.0b1/docs/static/pyproject.toml +29 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/pyproject.toml +16 -13
- {uedition-2.0.0a1 → uedition-2.0.0b1}/uedition/__about__.py +1 -1
- uedition-2.0.0b1/uedition/cli/__init__.py +18 -0
- uedition-2.0.0b1/uedition/cli/base.py +8 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/uedition/cli/build.py +22 -18
- uedition-2.0.0b1/uedition/cli/init.py +22 -0
- uedition-2.0.0b1/uedition/cli/language.py +63 -0
- uedition-2.0.0b1/uedition/cli/migrate.py +137 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/uedition/cli/serve.py +5 -2
- uedition-2.0.0b1/uedition/cli/update.py +84 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/uedition/ext/tei/builder.py +19 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/uedition/ext/tei/parser.py +18 -9
- uedition-2.0.0a1/docs/.uEdition.answers +0 -9
- uedition-2.0.0a1/docs/de/.uEdition.answers +0 -5
- uedition-2.0.0a1/docs/en/.uEdition.answers +0 -5
- uedition-2.0.0a1/docs/en/index.md +0 -70
- uedition-2.0.0a1/uedition/cli/__init__.py +0 -61
- uedition-2.0.0a1/uedition/cli/create.py +0 -10
- uedition-2.0.0a1/uedition/cli/language.py +0 -58
- uedition-2.0.0a1/uedition/cli/update.py +0 -16
- {uedition-2.0.0a1 → uedition-2.0.0b1}/.github/dependabot.yml +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/.github/workflows/codestyle.yml +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/.github/workflows/coverage.yml +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/.github/workflows/release.yml +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/.github/workflows/tests.yml +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/.gitignore +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/.pre-commit-config.yaml +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/.readthedocs.yml +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/LICENSE.txt +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/README.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/.gitignore +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/.readthedocs.yml +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/de/changelog.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/de/index.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/de/user/configuration.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/de/user/content.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/de/user/create.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/de/user/index.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/de/user/installation.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/de/user/language-add.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/de/user/language-update.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/de/user/publish.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/de/user/update.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/en/changelog.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/en/user/configuration.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/en/user/content.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/en/user/create.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/en/user/index.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/en/user/installation.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/en/user/language-add.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/en/user/language-update.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/en/user/publish.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/en/user/update.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/en/user/working-with-tei.tei +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/static/overrides.css +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/toc.yml +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/docs/uEdition.yml +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/__init__.py +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/conftest.py +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/fixtures/basic/uEdition.yml +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/fixtures/empty/.gitkeep +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/fixtures/multilang/.gitignore +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/fixtures/multilang/de/a-1-page.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/fixtures/multilang/de/a-2-page.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/fixtures/multilang/de/a-page.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/fixtures/multilang/de/b-page.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/fixtures/multilang/de/intro.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/fixtures/multilang/en/a-1-page.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/fixtures/multilang/en/a-2-page.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/fixtures/multilang/en/a-page.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/fixtures/multilang/en/b-page.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/fixtures/multilang/en/intro.md +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/fixtures/multilang/references.bib +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/fixtures/multilang/toc.yml +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/fixtures/multilang/uEdition.yaml +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/fixtures/yaml/uEdition.yaml +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/test_about.py +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/test_build.py +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/test_ext/test_config.py +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/test_ext/test_tei/__init__.py +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/test_ext/test_tei/test_parser.py +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/test_language.py +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/test_serve.py +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/test_settings.py +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tests/test_update.py +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/tox.ini +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/uedition/__init__.py +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/uedition/__main__.py +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/uedition/ext/__init__.py +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/uedition/ext/config.py +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/uedition/ext/language_switcher.css +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/uedition/ext/language_switcher.js +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/uedition/ext/language_switcher.py +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/uedition/ext/settings.py +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/uedition/ext/tei/__init__.py +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/uedition/ext/tei/tei_download.js +0 -0
- {uedition-2.0.0a1 → uedition-2.0.0b1}/uedition/settings.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: uEdition
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.0b1
|
|
4
4
|
Project-URL: Documentation, https://github.com/uEdition/uEdition#readme
|
|
5
5
|
Project-URL: Issues, https://github.com/uEdition/uEdition/issues
|
|
6
6
|
Project-URL: Source, https://github.com/uEdition/uEdition
|
|
@@ -16,16 +16,19 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
16
16
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
17
17
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
18
18
|
Requires-Python: >=3.10
|
|
19
|
-
Requires-Dist:
|
|
19
|
+
Requires-Dist: httpx<0.29,>=0.28.1
|
|
20
20
|
Requires-Dist: livereload
|
|
21
21
|
Requires-Dist: lxml<6.0.0,>=4.9.2
|
|
22
22
|
Requires-Dist: myst-parser<5,>=4.0.1
|
|
23
|
+
Requires-Dist: packaging==24.2
|
|
23
24
|
Requires-Dist: pydantic-settings<3.0.0,>=2.0.0
|
|
24
25
|
Requires-Dist: pydantic<3.0.0,>=2.0.0
|
|
25
26
|
Requires-Dist: pyyaml<7.0.0,>=6.0.0
|
|
26
27
|
Requires-Dist: sphinx-book-theme<2,>=1.1.4
|
|
27
28
|
Requires-Dist: sphinx-external-toc<2,>=1.0.1
|
|
28
29
|
Requires-Dist: sphinx<9,>=8.2.3
|
|
30
|
+
Requires-Dist: strictyaml<2,>=1.7.3
|
|
31
|
+
Requires-Dist: tomlkit<0.14,>=0.13.2
|
|
29
32
|
Requires-Dist: typer<1.0.0
|
|
30
33
|
Description-Content-Type: text/markdown
|
|
31
34
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# μEdition
|
|
2
|
+
|
|
3
|
+
The process of creating and making available a (critical) digital edition often presents projects with a range of significant
|
|
4
|
+
hurdles, particularly around technical knowledge and hosting costs. The μEdition is a framwork that lowers these barriers by
|
|
5
|
+
providing a simple tool that supports users in easily building (multi-lingual) digital editions that can then easily be made
|
|
6
|
+
available online using free or low-cost hosting solutions.
|
|
7
|
+
|
|
8
|
+
:::{admonition} Getting Help
|
|
9
|
+
:class: tip
|
|
10
|
+
|
|
11
|
+
The μEdition is still a young project and relies on your feedback to further lower the barriers to its use. Whether this is
|
|
12
|
+
adding documentation on how to do things, fixing broken things, or adding extra features, please let us know what is needed
|
|
13
|
+
and then we can make it better.
|
|
14
|
+
|
|
15
|
+
If you have any questions about anything related to the μEdition, please use our GitHub Discussions forum to ask:
|
|
16
|
+
[https://github.com/uEdition/uEdition/discussions](https://github.com/uEdition/uEdition/discussions).
|
|
17
|
+
|
|
18
|
+
If you run into any bugs, then please report these via the GitHub Issues and we can get them fixed:
|
|
19
|
+
[https://github.com/uEdition/uEdition/issues](https://github.com/uEdition/uEdition/issues).
|
|
20
|
+
:::
|
|
21
|
+
|
|
22
|
+
## Contents
|
|
23
|
+
|
|
24
|
+
:::{tableofcontents}
|
|
25
|
+
:::
|
|
26
|
+
|
|
27
|
+
## Quickstart
|
|
28
|
+
|
|
29
|
+
To quickly get started with the μEdition follow these steps:
|
|
30
|
+
|
|
31
|
+
1. Install [Hatch](https://hatch.pypa.io/latest/install/) for your operating system.
|
|
32
|
+
2. Create a new folder for your μEdition.
|
|
33
|
+
3. Download the default {download}`_static/pyproject.toml` and move that into your new folder.
|
|
34
|
+
4. Open a new terminal, change into your new folder and run the following command:
|
|
35
|
+
|
|
36
|
+
:::{code-block} console
|
|
37
|
+
hatch run init
|
|
38
|
+
:::
|
|
39
|
+
|
|
40
|
+
This creates the configuration file ({file}`uEdition.yml`) and table of contents ({file}`toc.yml`).
|
|
41
|
+
|
|
42
|
+
5. Then run the following command to add content in a new language:
|
|
43
|
+
|
|
44
|
+
:::{code-block} console
|
|
45
|
+
hatch run language add
|
|
46
|
+
:::
|
|
47
|
+
|
|
48
|
+
This will ask you a few questions about the new language and then create the required files.
|
|
49
|
+
|
|
50
|
+
5. Then run the following command to start the writing server:
|
|
51
|
+
|
|
52
|
+
:::{code-block} console
|
|
53
|
+
hatch run serve
|
|
54
|
+
:::
|
|
55
|
+
|
|
56
|
+
Your new μEdition will be available at http://localhost:8000.
|
|
@@ -18,12 +18,14 @@ Issues = "https://github.com/uEdition/uEdition/-/issues"
|
|
|
18
18
|
Source = "https://github.com/uEdition/uEdition/-"
|
|
19
19
|
|
|
20
20
|
[tool.hatch.envs.default]
|
|
21
|
-
dependencies = ["
|
|
21
|
+
dependencies = ["uEdition<2.1,>=2.0.0a2", "uEdition_editor<2.1,>=2.0.0a2"]
|
|
22
22
|
skip-install = true
|
|
23
23
|
|
|
24
24
|
[tool.hatch.envs.default.scripts]
|
|
25
25
|
build = "uEdition build {args}"
|
|
26
|
+
init = "uEdition init {args}"
|
|
26
27
|
serve = "uEdition serve {args}"
|
|
27
28
|
update = "uEdition update {args}"
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
migrate = "uEdition migrate {args}"
|
|
30
|
+
language = "uEdition language {args}"
|
|
31
|
+
edit = "uvicorn --port 8000 uedition_editor:app {args} {args}"
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "edition_name"
|
|
7
|
+
description = "edition_title"
|
|
8
|
+
requires-python = ">=3.10"
|
|
9
|
+
keywords = []
|
|
10
|
+
authors = [{ name = "author_name", email = "author_email@example.com" }]
|
|
11
|
+
classifiers = []
|
|
12
|
+
dependencies = []
|
|
13
|
+
version = "1.0.0"
|
|
14
|
+
|
|
15
|
+
[project.urls]
|
|
16
|
+
Documentation = "http://edition.com"
|
|
17
|
+
Issues = "http://edition.com"
|
|
18
|
+
Source = "http://edition.com"
|
|
19
|
+
|
|
20
|
+
[tool.hatch.envs.default]
|
|
21
|
+
dependencies = ["uEdition<2.1,>=2.0.0a2", "uEditor<2.1,>=2.0.0a2"]
|
|
22
|
+
skip-install = true
|
|
23
|
+
|
|
24
|
+
[tool.hatch.envs.default.scripts]
|
|
25
|
+
build = "uEdition build {args}"
|
|
26
|
+
serve = "uEdition serve {args}"
|
|
27
|
+
update = "uEdition update {args}"
|
|
28
|
+
migrate = "uEdition migrate {args}"
|
|
29
|
+
language = "uEdition language {args}"
|
|
@@ -3,6 +3,22 @@ requires = ["hatchling"]
|
|
|
3
3
|
build-backend = "hatchling.build"
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
|
+
dependencies = [
|
|
7
|
+
"httpx>=0.28.1,<0.29",
|
|
8
|
+
"lxml>=4.9.2,<6.0.0",
|
|
9
|
+
"livereload",
|
|
10
|
+
"myst-parser>=4.0.1,<5",
|
|
11
|
+
"packaging==24.2",
|
|
12
|
+
"pydantic>=2.0.0,<3.0.0",
|
|
13
|
+
"pydantic-settings>=2.0.0,<3.0.0",
|
|
14
|
+
"PyYAML>=6.0.0,<7.0.0",
|
|
15
|
+
"sphinx>=8.2.3,<9",
|
|
16
|
+
"sphinx_external_toc>=1.0.1,<2",
|
|
17
|
+
"sphinx-book-theme>=1.1.4,<2",
|
|
18
|
+
"strictyaml>=1.7.3,<2",
|
|
19
|
+
"tomlkit>=0.13.2,<0.14",
|
|
20
|
+
"typer<1.0.0",
|
|
21
|
+
]
|
|
6
22
|
name = "uEdition"
|
|
7
23
|
description = ''
|
|
8
24
|
readme = "README.md"
|
|
@@ -20,19 +36,6 @@ classifiers = [
|
|
|
20
36
|
"Programming Language :: Python :: Implementation :: CPython",
|
|
21
37
|
"Programming Language :: Python :: Implementation :: PyPy",
|
|
22
38
|
]
|
|
23
|
-
dependencies = [
|
|
24
|
-
"copier>=9.0.0,<10.0.0",
|
|
25
|
-
"lxml>=4.9.2,<6.0.0",
|
|
26
|
-
"livereload",
|
|
27
|
-
"myst-parser>=4.0.1,<5",
|
|
28
|
-
"pydantic>=2.0.0,<3.0.0",
|
|
29
|
-
"pydantic-settings>=2.0.0,<3.0.0",
|
|
30
|
-
"PyYAML>=6.0.0,<7.0.0",
|
|
31
|
-
"sphinx>=8.2.3,<9",
|
|
32
|
-
"sphinx_external_toc>=1.0.1,<2",
|
|
33
|
-
"sphinx-book-theme>=1.1.4,<2",
|
|
34
|
-
"typer<1.0.0",
|
|
35
|
-
]
|
|
36
39
|
dynamic = ["version"]
|
|
37
40
|
|
|
38
41
|
[project.scripts]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2023-present Mark Hall <mark.hall@work.room3b.eu>
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
"""uEdtion Command-line Tool."""
|
|
5
|
+
|
|
6
|
+
from rich import print as output
|
|
7
|
+
|
|
8
|
+
from uedition.__about__ import __version__
|
|
9
|
+
from uedition.cli import build, init, language, migrate, serve, update # noqa:F401
|
|
10
|
+
from uedition.cli.base import app
|
|
11
|
+
from uedition.settings import settings
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@app.command()
|
|
15
|
+
def version() -> None:
|
|
16
|
+
"""Output the current μEdition version."""
|
|
17
|
+
output(f"μEdition: {__version__}")
|
|
18
|
+
output(f"Configuration: {settings['version']}")
|
|
@@ -10,6 +10,7 @@ from shutil import copytree, ignore_patterns, rmtree
|
|
|
10
10
|
|
|
11
11
|
from yaml import safe_dump, safe_load
|
|
12
12
|
|
|
13
|
+
from uedition.cli.base import app
|
|
13
14
|
from uedition.settings import NoConfigError, reload_settings, settings
|
|
14
15
|
|
|
15
16
|
LANDING_PAGE_TEMPLATE = """\
|
|
@@ -187,18 +188,19 @@ def full_build(lang: dict) -> None:
|
|
|
187
188
|
check=False,
|
|
188
189
|
shell=False,
|
|
189
190
|
)
|
|
190
|
-
|
|
191
|
-
path.join("_build", lang["path"], "html"),
|
|
192
|
-
path.join(settings["output"]["path"], lang["path"]),
|
|
193
|
-
dirs_exist_ok=True,
|
|
194
|
-
)
|
|
195
|
-
if settings["output"]["tei"]:
|
|
191
|
+
if path.isdir(path.join("_build", lang["path"], "html")):
|
|
196
192
|
copytree(
|
|
197
|
-
path.join("_build", lang["path"], "
|
|
193
|
+
path.join("_build", lang["path"], "html"),
|
|
198
194
|
path.join(settings["output"]["path"], lang["path"]),
|
|
199
|
-
ignore=ignore_patterns("_sphinx_design_static"),
|
|
200
195
|
dirs_exist_ok=True,
|
|
201
196
|
)
|
|
197
|
+
if settings["output"]["tei"] and path.isdir(path.join("_build", lang["path"], "tei")):
|
|
198
|
+
copytree(
|
|
199
|
+
path.join("_build", lang["path"], "tei"),
|
|
200
|
+
path.join(settings["output"]["path"], lang["path"]),
|
|
201
|
+
ignore=ignore_patterns("_sphinx_design_static"),
|
|
202
|
+
dirs_exist_ok=True,
|
|
203
|
+
)
|
|
202
204
|
|
|
203
205
|
|
|
204
206
|
def partial_build(lang: dict) -> None:
|
|
@@ -227,22 +229,24 @@ def partial_build(lang: dict) -> None:
|
|
|
227
229
|
check=False,
|
|
228
230
|
shell=False,
|
|
229
231
|
)
|
|
230
|
-
|
|
231
|
-
path.join("_build", lang["path"], "html"),
|
|
232
|
-
path.join(settings["output"]["path"], lang["path"]),
|
|
233
|
-
dirs_exist_ok=True,
|
|
234
|
-
)
|
|
235
|
-
if settings["output"]["tei"]:
|
|
232
|
+
if path.isdir(path.join("_build", lang["path"], "html")):
|
|
236
233
|
copytree(
|
|
237
|
-
path.join("_build", lang["path"], "
|
|
234
|
+
path.join("_build", lang["path"], "html"),
|
|
238
235
|
path.join(settings["output"]["path"], lang["path"]),
|
|
239
|
-
ignore=ignore_patterns("_sphinx_design_static"),
|
|
240
236
|
dirs_exist_ok=True,
|
|
241
237
|
)
|
|
238
|
+
if settings["output"]["tei"] and path.isdir(path.join("_build", lang["path"], "tei")):
|
|
239
|
+
copytree(
|
|
240
|
+
path.join("_build", lang["path"], "tei"),
|
|
241
|
+
path.join(settings["output"]["path"], lang["path"]),
|
|
242
|
+
ignore=ignore_patterns("_sphinx_design_static"),
|
|
243
|
+
dirs_exist_ok=True,
|
|
244
|
+
)
|
|
242
245
|
|
|
243
246
|
|
|
244
|
-
|
|
245
|
-
|
|
247
|
+
@app.command()
|
|
248
|
+
def build() -> None:
|
|
249
|
+
"""Build the full μEdition."""
|
|
246
250
|
if not path.exists("uEdition.yml") and not path.exists("uEdition.yaml"):
|
|
247
251
|
raise NoConfigError()
|
|
248
252
|
if path.exists(settings["output"]["path"]):
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2023-present Mark Hall <mark.hall@work.room3b.eu>
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
"""Local server that automatically rebuilds on changes."""
|
|
5
|
+
|
|
6
|
+
from os import path
|
|
7
|
+
|
|
8
|
+
from yaml import safe_dump
|
|
9
|
+
|
|
10
|
+
from uedition.cli.base import app
|
|
11
|
+
from uedition.settings import NoConfigError
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@app.command()
|
|
15
|
+
def init(force: bool = False) -> None: # noqa: ARG001 FBT001 FBT002
|
|
16
|
+
"""Initialise a new μEdition."""
|
|
17
|
+
if path.exists("uEdition.yml") and path.exists("uEdition.yaml"):
|
|
18
|
+
raise NoConfigError()
|
|
19
|
+
with open("uEdition.yml", "w") as out_f:
|
|
20
|
+
safe_dump({"version": "2", "output": "site"}, out_f)
|
|
21
|
+
with open("toc.yml", "w") as out_f:
|
|
22
|
+
safe_dump({"format": "jb-book", "root": "index"}, out_f)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2023-present Mark Hall <mark.hall@work.room3b.eu>
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
"""The μEdition language functionality."""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
from typing import Annotated
|
|
8
|
+
|
|
9
|
+
from rich import print as output
|
|
10
|
+
from typer import Option, Typer
|
|
11
|
+
from yaml import safe_dump, safe_load
|
|
12
|
+
|
|
13
|
+
from uedition.cli.base import app
|
|
14
|
+
from uedition.settings import NoConfigError
|
|
15
|
+
|
|
16
|
+
lang_app = Typer(help="Language configuration functionality")
|
|
17
|
+
app.add_typer(lang_app, name="language")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@lang_app.command()
|
|
21
|
+
def add(
|
|
22
|
+
code: Annotated[str, Option(prompt="Language code")],
|
|
23
|
+
label: Annotated[
|
|
24
|
+
str,
|
|
25
|
+
Option(prompt="Language name"),
|
|
26
|
+
],
|
|
27
|
+
title: Annotated[str, Option(prompt="Title")],
|
|
28
|
+
path: str | None = None,
|
|
29
|
+
) -> None:
|
|
30
|
+
"""Add a language."""
|
|
31
|
+
if path is None:
|
|
32
|
+
path = code
|
|
33
|
+
if os.path.exists("uEdition.yml"):
|
|
34
|
+
with open("uEdition.yml") as in_f:
|
|
35
|
+
config = safe_load(in_f)
|
|
36
|
+
elif os.path.exists("uEdition.yaml"):
|
|
37
|
+
with open("uEdition.yaml") as in_f:
|
|
38
|
+
config = safe_load(in_f)
|
|
39
|
+
else:
|
|
40
|
+
raise NoConfigError()
|
|
41
|
+
if "languages" not in config:
|
|
42
|
+
config["languages"] = []
|
|
43
|
+
for lang in config["languages"]:
|
|
44
|
+
if lang["code"] == code:
|
|
45
|
+
output(
|
|
46
|
+
"[red bold]The language code [/red bold]"
|
|
47
|
+
f"[cyan bold]{code}[/cyan bold]"
|
|
48
|
+
"[red bold] is already configured[/red bold]"
|
|
49
|
+
)
|
|
50
|
+
return
|
|
51
|
+
if os.path.exists(path):
|
|
52
|
+
output(
|
|
53
|
+
f"[red bold]The target path [/red bold][cyan bold]{code}[/cyan bold][red bold] already exists.[/red bold]"
|
|
54
|
+
)
|
|
55
|
+
os.mkdir(path)
|
|
56
|
+
config["languages"].append({"code": code, "label": label, "path": path})
|
|
57
|
+
if "title" not in config:
|
|
58
|
+
config["title"] = {}
|
|
59
|
+
config["title"][code] = title
|
|
60
|
+
with open("uEdition.yml", "w") as out_f:
|
|
61
|
+
safe_dump(config, out_f)
|
|
62
|
+
with open(os.path.join(path, "index.md"), "w") as out_f:
|
|
63
|
+
out_f.write(f"# {title}\n")
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2023-present Mark Hall <mark.hall@work.room3b.eu>
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
"""The μEdition migration functionality."""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
from os import path
|
|
8
|
+
|
|
9
|
+
import tomlkit
|
|
10
|
+
from rich import print as output
|
|
11
|
+
|
|
12
|
+
from uedition.cli.base import app
|
|
13
|
+
from uedition.settings import NoConfigError
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def cleanup_old_files() -> None:
|
|
17
|
+
"""Cleanup any old files."""
|
|
18
|
+
# Scan for old files to remove
|
|
19
|
+
old_copier_files = []
|
|
20
|
+
old_config_files = []
|
|
21
|
+
for basepath, _, filenames in os.walk("."):
|
|
22
|
+
for filename in filenames:
|
|
23
|
+
if filename == ".uEdition.answers":
|
|
24
|
+
old_copier_files.append(path.join(basepath, filename))
|
|
25
|
+
elif filename in ("_config.yaml", "_config.yml"):
|
|
26
|
+
old_config_files.append(path.join(basepath, filename))
|
|
27
|
+
# Remove old copier files (v2.0.0)
|
|
28
|
+
if len(old_copier_files) > 0:
|
|
29
|
+
output(":broom: Removing old configuration answers")
|
|
30
|
+
for filename in old_copier_files:
|
|
31
|
+
os.unlink(filename)
|
|
32
|
+
# Remove old config files (v2.0.0)
|
|
33
|
+
if len(old_config_files) > 0:
|
|
34
|
+
output(":broom: Removing old configuration files")
|
|
35
|
+
for filename in old_config_files:
|
|
36
|
+
os.unlink(filename)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def cleanup_gitignore() -> None:
|
|
40
|
+
"""Cleanup the gitignore."""
|
|
41
|
+
# Update .gitignore (v2.0.0)
|
|
42
|
+
if path.isfile(".gitignore"):
|
|
43
|
+
with open(".gitignore") as in_f:
|
|
44
|
+
lines = in_f.readlines()
|
|
45
|
+
original_length = len(lines)
|
|
46
|
+
lines = [line for line in lines if line.strip() not in ("_config.yml", "_config.yaml")]
|
|
47
|
+
found = False
|
|
48
|
+
for line in lines:
|
|
49
|
+
if line.strip() == "conf.py":
|
|
50
|
+
found = True
|
|
51
|
+
if not found or len(lines) != original_length:
|
|
52
|
+
output(":broom: Updating the .gitignore")
|
|
53
|
+
if not found:
|
|
54
|
+
lines.append("conf.py\n")
|
|
55
|
+
with open(".gitignore", "w") as out_f:
|
|
56
|
+
for line in lines:
|
|
57
|
+
out_f.write(line)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def cleanup_pyproject() -> None:
|
|
61
|
+
"""Cleanup the pyproject file."""
|
|
62
|
+
if not path.exists("pyproject.toml"):
|
|
63
|
+
raise NoConfigError()
|
|
64
|
+
with open("pyproject.toml") as in_f:
|
|
65
|
+
pyproject = tomlkit.parse(in_f.read())
|
|
66
|
+
updated = False
|
|
67
|
+
if "tool" not in pyproject:
|
|
68
|
+
pyproject["tool"] = tomlkit.table()
|
|
69
|
+
if "hatch" not in pyproject["tool"]:
|
|
70
|
+
pyproject["tool"]["hatch"] = tomlkit.table()
|
|
71
|
+
if "envs" not in pyproject["tool"]["hatch"]:
|
|
72
|
+
pyproject["tool"]["hatch"]["envs"] = tomlkit.table()
|
|
73
|
+
if "default" not in pyproject["tool"]["hatch"]["envs"]:
|
|
74
|
+
pyproject["tool"]["hatch"]["envs"]["default"] = tomlkit.table()
|
|
75
|
+
if "scripts" not in pyproject["tool"]["hatch"]["envs"]["default"]:
|
|
76
|
+
pyproject["tool"]["hatch"]["envs"]["default"]["scripts"] = tomlkit.table()
|
|
77
|
+
updated = True
|
|
78
|
+
if "add-language" in pyproject["tool"]["hatch"]["envs"]["default"]["scripts"]:
|
|
79
|
+
del pyproject["tool"]["hatch"]["envs"]["default"]["scripts"]["add-language"]
|
|
80
|
+
updated = True
|
|
81
|
+
if "update-language" in pyproject["tool"]["hatch"]["envs"]["default"]["scripts"]:
|
|
82
|
+
del pyproject["tool"]["hatch"]["envs"]["default"]["scripts"]["update-language"]
|
|
83
|
+
updated = True
|
|
84
|
+
if "migrate" not in pyproject["tool"]["hatch"]["envs"]["default"]["scripts"]:
|
|
85
|
+
pyproject["tool"]["hatch"]["envs"]["default"]["scripts"]["migrate"] = "uEdition migrate {args}"
|
|
86
|
+
updated = True
|
|
87
|
+
if "language" not in pyproject["tool"]["hatch"]["envs"]["default"]["scripts"]:
|
|
88
|
+
pyproject["tool"]["hatch"]["envs"]["default"]["scripts"]["language"] = "uEdition language {args}"
|
|
89
|
+
updated = True
|
|
90
|
+
if "init" not in pyproject["tool"]["hatch"]["envs"]["default"]["scripts"]:
|
|
91
|
+
pyproject["tool"]["hatch"]["envs"]["default"]["scripts"]["init"] = "uEdition init {args}"
|
|
92
|
+
updated = True
|
|
93
|
+
if "edit" not in pyproject["tool"]["hatch"]["envs"]["default"]["scripts"]:
|
|
94
|
+
pyproject["tool"]["hatch"]["envs"]["default"]["scripts"]["edit"] = (
|
|
95
|
+
"uvicorn --port 8000 uedition_editor:app {args} {args}"
|
|
96
|
+
)
|
|
97
|
+
updated = True
|
|
98
|
+
if updated:
|
|
99
|
+
output(":broom: Updating the pyproject.toml")
|
|
100
|
+
with open("pyproject.toml", "w") as out_f:
|
|
101
|
+
tomlkit.dump(pyproject, out_f)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def migrate_ueditor() -> None:
|
|
105
|
+
"""Migrate the μEditor to the latest supported version."""
|
|
106
|
+
ueditor_version = "uedition_editor>=2.0.0b5,<2.1"
|
|
107
|
+
output(":hammer: Updating the μEditor")
|
|
108
|
+
with open("pyproject.toml") as in_f:
|
|
109
|
+
pyproject = tomlkit.parse(in_f.read())
|
|
110
|
+
found_ueditor = False
|
|
111
|
+
for idx, dep in enumerate(pyproject["tool"]["hatch"]["envs"]["default"]["dependencies"]):
|
|
112
|
+
dep = dep.lower() # noqa:PLW2901
|
|
113
|
+
if (
|
|
114
|
+
dep == "uedition_editor"
|
|
115
|
+
or dep.startswith("uedition_editor=")
|
|
116
|
+
or dep.startswith("uedition_editor<")
|
|
117
|
+
or dep.startswith("uedition_editor>")
|
|
118
|
+
):
|
|
119
|
+
pyproject["tool"]["hatch"]["envs"]["default"]["dependencies"][idx] = ueditor_version
|
|
120
|
+
found_ueditor = True
|
|
121
|
+
if not found_ueditor:
|
|
122
|
+
pyproject["tool"]["hatch"]["envs"]["default"]["dependencies"].append(ueditor_version)
|
|
123
|
+
with open("pyproject.toml", "w") as out_f:
|
|
124
|
+
tomlkit.dump(pyproject, out_f)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@app.command()
|
|
128
|
+
def migrate() -> None:
|
|
129
|
+
"""Migrate the μEdition to the latest version."""
|
|
130
|
+
if not path.exists("uEdition.yml") and not path.exists("uEdition.yaml") and not path.exists("pyproject.toml"):
|
|
131
|
+
raise NoConfigError()
|
|
132
|
+
output(":hammer: Migrating the μEdition")
|
|
133
|
+
cleanup_old_files()
|
|
134
|
+
cleanup_gitignore()
|
|
135
|
+
cleanup_pyproject()
|
|
136
|
+
migrate_ueditor()
|
|
137
|
+
output(":checkered_flag: Migration complete")
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
#
|
|
3
3
|
# SPDX-License-Identifier: MIT
|
|
4
4
|
"""Local server that automatically rebuilds on changes."""
|
|
5
|
+
|
|
5
6
|
from os import path
|
|
6
7
|
from typing import Callable
|
|
7
8
|
|
|
8
9
|
from livereload import Server
|
|
9
10
|
|
|
11
|
+
from uedition.cli.base import app
|
|
10
12
|
from uedition.cli.build import full_build, partial_build
|
|
11
13
|
from uedition.settings import NoConfigError, settings
|
|
12
14
|
|
|
@@ -27,8 +29,9 @@ def build_cmd(lang: dict, full: bool = True) -> Callable[[], None]: # noqa: FBT
|
|
|
27
29
|
return cmd
|
|
28
30
|
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
@app.command()
|
|
33
|
+
def serve() -> None:
|
|
34
|
+
"""Run the local μEdition writing server."""
|
|
32
35
|
if not path.exists("uEdition.yml") and not path.exists("uEdition.yaml"):
|
|
33
36
|
raise NoConfigError()
|
|
34
37
|
full_rebuilds = [build_cmd(lang, full=True) for lang in settings["languages"]]
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2023-present Mark Hall <mark.hall@work.room3b.eu>
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
"""The μEdition update functionality."""
|
|
5
|
+
|
|
6
|
+
from enum import Enum
|
|
7
|
+
from os import path
|
|
8
|
+
|
|
9
|
+
import httpx
|
|
10
|
+
import tomlkit
|
|
11
|
+
from packaging.specifiers import SpecifierSet
|
|
12
|
+
from packaging.version import Version
|
|
13
|
+
from rich import print as output
|
|
14
|
+
|
|
15
|
+
from uedition.cli.base import app
|
|
16
|
+
from uedition.settings import NoConfigError
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class UpdateVersionOptions(Enum):
|
|
20
|
+
"""Option settings for upgrade version selection."""
|
|
21
|
+
|
|
22
|
+
RELEASES = "releases"
|
|
23
|
+
PRE_RELEASES = "pre-releases"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@app.command()
|
|
27
|
+
def update(allow_versions: UpdateVersionOptions = UpdateVersionOptions.RELEASES.value) -> None:
|
|
28
|
+
"""Update the μEdition to the latest version."""
|
|
29
|
+
try:
|
|
30
|
+
if not path.exists("uEdition.yml") and not path.exists("uEdition.yaml") and not path.exists("pyproject.toml"):
|
|
31
|
+
raise NoConfigError()
|
|
32
|
+
with open("pyproject.toml") as in_f:
|
|
33
|
+
pyproject = tomlkit.parse(in_f.read())
|
|
34
|
+
output(":hourglass_flowing_sand: Determining latest version")
|
|
35
|
+
response = httpx.get(
|
|
36
|
+
"https://pypi.org/simple/uedition/", headers={"Accept": "application/vnd.pypi.simple.v1+json"}
|
|
37
|
+
)
|
|
38
|
+
if response.status_code != 200: # noqa: PLR2004
|
|
39
|
+
output(":cross_mark: Failed to determine the latest version")
|
|
40
|
+
raise Exception("PyPi access error") # noqa: EM101
|
|
41
|
+
versions = response.json()["versions"]
|
|
42
|
+
versions.reverse()
|
|
43
|
+
target_version = None
|
|
44
|
+
for version in versions:
|
|
45
|
+
if Version(version).is_prerelease and allow_versions == UpdateVersionOptions.PRE_RELEASES:
|
|
46
|
+
target_version = Version(version)
|
|
47
|
+
break
|
|
48
|
+
elif not Version(version).is_prerelease:
|
|
49
|
+
target_version = Version(version)
|
|
50
|
+
break
|
|
51
|
+
if target_version is None:
|
|
52
|
+
raise Exception("No version found to upgrade to") # noqa: EM101
|
|
53
|
+
target_specifier = SpecifierSet(f">={target_version},<{target_version.major}.{target_version.minor + 1}")
|
|
54
|
+
output(f":hammer: Upgrading to {target_version}")
|
|
55
|
+
if "tool" not in pyproject:
|
|
56
|
+
pyproject["tool"] = tomlkit.table()
|
|
57
|
+
if "hatch" not in pyproject["tool"]:
|
|
58
|
+
pyproject["tool"]["hatch"] = tomlkit.table()
|
|
59
|
+
if "envs" not in pyproject["tool"]["hatch"]:
|
|
60
|
+
pyproject["tool"]["hatch"]["envs"] = tomlkit.table()
|
|
61
|
+
if "default" not in pyproject["tool"]["hatch"]["envs"]:
|
|
62
|
+
pyproject["tool"]["hatch"]["envs"]["default"] = tomlkit.table()
|
|
63
|
+
if "dependencies" not in pyproject["tool"]["hatch"]["envs"]["default"]:
|
|
64
|
+
pyproject["tool"]["hatch"]["envs"]["default"]["dependencies"] = []
|
|
65
|
+
pyproject["tool"]["hatch"]["envs"]["default"]["skip-install"] = True
|
|
66
|
+
# Upgrade the uEdition version
|
|
67
|
+
found_uedition = False
|
|
68
|
+
for idx, dep in enumerate(pyproject["tool"]["hatch"]["envs"]["default"]["dependencies"]):
|
|
69
|
+
dep = dep.lower() # noqa:PLW2901
|
|
70
|
+
if (
|
|
71
|
+
dep == "uedition"
|
|
72
|
+
or dep.startswith("uedition=")
|
|
73
|
+
or dep.startswith("uedition<")
|
|
74
|
+
or dep.startswith("uedition>")
|
|
75
|
+
):
|
|
76
|
+
pyproject["tool"]["hatch"]["envs"]["default"]["dependencies"][idx] = f"uedition{target_specifier}"
|
|
77
|
+
found_uedition = True
|
|
78
|
+
if not found_uedition:
|
|
79
|
+
pyproject["tool"]["hatch"]["envs"]["default"]["dependencies"].append(f"uedition{target_specifier}")
|
|
80
|
+
with open("pyproject.toml", "w") as out_f:
|
|
81
|
+
tomlkit.dump(pyproject, out_f)
|
|
82
|
+
output(":checkered_flag: Upgrade complete")
|
|
83
|
+
except Exception as e:
|
|
84
|
+
output(f":cross_mark: Update failed: {e}")
|
|
@@ -14,6 +14,8 @@ from sphinx.locale import __
|
|
|
14
14
|
from sphinx.util.osutil import ensuredir, os_path
|
|
15
15
|
from sphinx.writers.xml import XMLWriter
|
|
16
16
|
|
|
17
|
+
from uedition.ext.tei.parser import TeiElement
|
|
18
|
+
|
|
17
19
|
logger = logging.getLogger(__name__)
|
|
18
20
|
|
|
19
21
|
MAPPINGS = [
|
|
@@ -37,6 +39,13 @@ MAPPINGS = [
|
|
|
37
39
|
},
|
|
38
40
|
{"cls": nodes.compound, "tagname": "div", "type": "block"},
|
|
39
41
|
{"cls": nodes.admonition, "tagname": "div", "type": "block"},
|
|
42
|
+
{
|
|
43
|
+
"cls": nodes.definition_list,
|
|
44
|
+
"tagname": "list",
|
|
45
|
+
"type": "block",
|
|
46
|
+
"attrs": [{"target": "type", "value": "definition"}],
|
|
47
|
+
},
|
|
48
|
+
{"cls": nodes.definition_list_item, "tagname": "item", "type": "block"},
|
|
40
49
|
{"cls": sphinx.addnodes.toctree},
|
|
41
50
|
{
|
|
42
51
|
"cls": nodes.footnote,
|
|
@@ -105,6 +114,16 @@ class TEITranslator(nodes.GenericNodeVisitor):
|
|
|
105
114
|
for rule in MAPPINGS:
|
|
106
115
|
if isinstance(node, rule["cls"]):
|
|
107
116
|
return rule
|
|
117
|
+
if isinstance(node, TeiElement):
|
|
118
|
+
tag = node.get("tei_tag")
|
|
119
|
+
tag = tag[tag.find("}") + 1 :]
|
|
120
|
+
attrs = []
|
|
121
|
+
for key, value in node.get("tei_attributes").items():
|
|
122
|
+
if key.startswith("data-tei-block-") or key.startswith("data-tei-mark-"):
|
|
123
|
+
continue
|
|
124
|
+
elif key.startswith("data-tei-attribute-"):
|
|
125
|
+
attrs.append({"target": key[19:], "value": value})
|
|
126
|
+
return {"tagname": tag, "type": "block", "attrs": attrs}
|
|
108
127
|
self.warn(f"Unknown node {node.__class__.__module__}.{node.__class__.__qualname__} ({node.attlist()})")
|
|
109
128
|
return {"tagname": "div", "type": "block"}
|
|
110
129
|
|