diff --git a/Makefile b/Makefile index a88390921..fe4e0056f 100644 --- a/Makefile +++ b/Makefile @@ -137,7 +137,7 @@ docs: mkdocs uml ## Generate documentation and UML .PHONY: mkdocs mkdocs: install $(MKDOCS_INDEX) -$(MKDOCS_INDEX): docs/requirements.txt mkdocs.yml docs/*.md +$(MKDOCS_INDEX): docs/requirements.txt mkdocs.yml docs/**/*.md @ mkdir -p docs/about @ cd docs && ln -sf ../README.md index.md @ cd docs/about && ln -sf ../../CHANGELOG.md changelog.md diff --git a/docs/cli/publishing.md b/docs/cli/publishing.md index 095dba0da..0781c077d 100644 --- a/docs/cli/publishing.md +++ b/docs/cli/publishing.md @@ -159,11 +159,11 @@ The example generated markdown will look something like this: Steamboat Willie **shall** whistle while he is driving his boat. -| Attribute | Value | -| --------- | ----- | -| commentary | The song should be a happy tune | -| rationale | Whistling will help demonstrate that Steamboat Willie is having a good time and is care-free. | -| invented-by | Donald | +| Attribute | Value | +| ----------- | --------------------------------------------------------------------------------------------- | +| commentary | The song should be a happy tune | +| rationale | Whistling will help demonstrate that Steamboat Willie is having a good time and is care-free. | +| invented-by | Donald | ``` -More information about attributes can be found in the [item](item.md#extended-item-attributes) description and [document](document.md#extended-document-attributes) extended attributes sections. +More information about attributes can be found in the [item](../reference/item.md#extended-item-attributes) description and [document](../reference/document.md#extended-document-attributes) extended attributes sections. \ No newline at end of file diff --git a/docs/getting-started/setup.md b/docs/getting-started/setup.md index 2989b2c4d..e589749f6 100644 --- a/docs/getting-started/setup.md +++ b/docs/getting-started/setup.md @@ -39,3 +39,134 @@ so the solution is to add the following to your `.gitattributes` file: From [Git's documentation](https://git-scm.com/docs/gitattributes): > This setting forces Git to normalize line endings [for \*.yml files] to LF on checkin and prevents conversion to CRLF when the file is checked out. + +## Optional Dependencies + +Doorstop has minimal core dependencies, but certain features require additional tools to be installed on your system. + +### LaTeX Publishing + +To publish documents in LaTeX/PDF format, you need a LaTeX distribution installed: + +#### Windows + +Download and install [MiKTeX](https://miktex.org/download): + +```powershell +winget install MiKTeX.MiKTeX +``` + +#### Linux (Debian/Ubuntu) + +```sh +sudo apt-get update +sudo apt-get install texlive-latex-base texlive-latex-extra +``` + +#### macOS + +```sh +brew install --cask mactex +``` + +#### Verification + +After installation, verify that `pdflatex` is available: + +```sh +pdflatex --version +``` + +### PlantUML Diagrams in LaTeX + +If your documents contain PlantUML diagrams (using ` ​```plantuml` code blocks) and you want to publish them to LaTeX/PDF, you need three additional tools: + +1. **Java Runtime Environment** (to run PlantUML) +2. **PlantUML** (to generate diagrams) +3. **Inkscape** (to convert SVG diagrams to PDF) + +#### Windows Installation + +```powershell +# Install Java Runtime (required for PlantUML) +winget install EclipseAdoptium.Temurin.17.JRE + +# Install PlantUML +winget install PlantUML.PlantUML + +# Install Inkscape (for SVG to PDF conversion) +winget install Inkscape.Inkscape +``` + +!!! warning "Add Inkscape to PATH" + After installing Inkscape on Windows, you **must** add it to your PATH. + +#### Linux Installation (Debian/Ubuntu) + +```sh +sudo apt-get update +sudo apt-get install default-jre plantuml inkscape +``` + +#### macOS Installation + +```sh +brew install openjdk plantuml inkscape +``` + +### Verification + +Verify all dependencies are installed correctly: + +```sh +java -version +plantuml -version +inkscape --version +``` + +!!! info "Inkscape Version Compatibility" + Doorstop requires **Inkscape 1.0 or later**. Older versions used different command-line syntax that is not compatible. + +### Troubleshooting +#### Windows: "inkscape: command not found" + +**Cause:** Inkscape is not in your PATH. + +**Solution:** + +1. Verify Inkscape is installed: Check if `C:\Program Files\Inkscape\bin\inkscape.exe` exists +2. Add to PATH as described above +3. **Restart your terminal** - existing terminals won't see the PATH changes +4. Test: `inkscape --version` + +#### LaTeX: "PlantUML diagram not found" + +**Cause:** PlantUML diagrams require the `title` attribute. + +**Solution:** Ensure all PlantUML code blocks have a title: + +````markdown +```plantuml title="System Architecture" +@startuml +Alice -> Bob: Hello +@enduml +``` +```` + +Without the `title` attribute, Doorstop cannot determine the filename for the generated diagram. + +#### Security Note: Shell Escape + +!!! warning "Shell Escape Security" + LaTeX publishing with PlantUML requires `pdflatex` to be run with the `-shell-escape` flag, which allows LaTeX to execute external commands (like `plantuml` and `inkscape`). + + The generated `compile.sh` script automatically uses this flag. Be aware of the [security implications](https://tex.stackexchange.com/questions/88740/what-does-shell-escape-do) when compiling LaTeX files from untrusted sources. + +### Summary Table + +| Feature | Required Tools | +| ------------------------ | ------------------------------------ | +| **LaTeX/PDF Publishing** | LaTeX distribution (MiKTeX/TeX Live) | +| **PlantUML in LaTeX** | LaTeX + Java + PlantUML + Inkscape | +| **HTML Publishing** | *(no additional tools required)* | +| **Markdown Publishing** | *(no additional tools required)* | diff --git a/doorstop/core/files/templates/latex/doorstop.cls b/doorstop/core/files/templates/latex/doorstop.cls index 2db72044f..d3483a694 100644 --- a/doorstop/core/files/templates/latex/doorstop.cls +++ b/doorstop/core/files/templates/latex/doorstop.cls @@ -91,9 +91,9 @@ % Call PlantUML to produce a svg vector graphcis: \immediate\write18{plantuml -tsvg #1.txt} % Call Inkscape to convert the svg to a pdf (pdflatex cannot use svg): - \immediate\write18{inkscape #1.svg --export-pdf=#1.pdf} + \immediate\write18{inkscape #1.svg --export-filename=#1.pdf} % Include the pdf: - \begin{figure}[!h] + \begin{figure}[!h] \includegraphics[width=#2]{#1.pdf} \caption{#3} \label{fig:plant#4}\zlabel{fig:plant#4} diff --git a/doorstop/core/publishers/latex.py b/doorstop/core/publishers/latex.py index c0af64a0f..4c205a3f0 100644 --- a/doorstop/core/publishers/latex.py +++ b/doorstop/core/publishers/latex.py @@ -598,13 +598,15 @@ def _generate_latex_wrapper(self): """Generate all wrapper scripts required for typesetting in LaTeX.""" # Check for defined document attributes. doc_attributes = get_document_attributes(self.document) + # Sanitize the document name for use as filename (replace spaces with hyphens) + safe_name = doc_attributes["name"].replace(" ", "-") # Create the wrapper file. head, tail = os.path.split(self.documentPath) if tail != extract_prefix(self.document) + ".tex": log.warning( "LaTeX export does not support custom file names. Change in .doorstop.yml instead." ) - tail = doc_attributes["name"] + ".tex" + tail = safe_name + ".tex" self.documentPath = os.path.join(head, extract_prefix(self.document) + ".tex") wrapperPath = os.path.join(head, tail) # Load template data. @@ -714,6 +716,8 @@ def _generate_latex_wrapper(self): external_doc_attributes = get_document_attributes(external) # Don't add self. if external_doc_attributes["name"] != doc_attributes["name"]: + # Sanitize external document name for use as filename (replace spaces with hyphens) + external_safe_name = external_doc_attributes["name"].replace(" ", "-") if not info_text_set: wrapper = _add_comment( wrapper, @@ -721,15 +725,9 @@ def _generate_latex_wrapper(self): ) info_text_set = True wrapper.append( - "\\zexternaldocument{{{n}}}".format( - n=external_doc_attributes["name"] - ) - ) - wrapper.append( - "\\externaldocument{{{n}}}".format( - n=external_doc_attributes["name"] - ) + "\\zexternaldocument{{{n}}}".format(n=external_safe_name) ) + wrapper.append("\\externaldocument{{{n}}}".format(n=external_safe_name)) if info_text_set: wrapper = _add_comment(wrapper, "END external references.") wrapper.append("") @@ -772,6 +770,4 @@ def _generate_latex_wrapper(self): common.write_lines(wrapper, wrapperPath, end=settings.WRITE_LINESEPERATOR) # Add to compile.sh as return value. - return "pdflatex -halt-on-error -shell-escape {n}.tex".format( - n=doc_attributes["name"] - ) + return 'pdflatex -halt-on-error -shell-escape "{n}.tex"'.format(n=safe_name) diff --git a/poetry.lock b/poetry.lock index fb166a6a7..802e9d179 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.3.1 and should not be changed by hand. [[package]] name = "altgraph" @@ -960,7 +960,7 @@ files = [ ] [package.dependencies] -astroid = ">=3.2.4,<=3.3.0-dev0" +astroid = ">=3.2.4,<=3.3.0.dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = [ {version = ">=0.2", markers = "python_version < \"3.11\""},