Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,25 @@ Instructions: Add a subsection under `[Unreleased]` for additions, fixes, change

## [Unreleased]

### Fixed

- Improve custom `ol` markers in HTML output, especially for safari browsers.
- Doenet loading improvements
- Workspace and solutions for printouts work better (in the right order).
- Asymptote rendering recognizes the version of asymptote installed (and reacts accordingly).

### Changed

- `pretext validate` now follows core, which checks the source against both schemas in one pass and adds a survey of the experimental constructs in use to the report. An experimental construct is not an error, so it no longer makes validation exit non-zero; it is counted and reported separately, since its markup may change without a deprecation cycle.
- `pretext validate --method` now selects only where the checks run: `local` (an installed jing, the default) or `server` (jing as a remote service). The shape of the report has moved to `pretext validate --report-form`: `full` (the default) or `terse` (machine-readable, one tab-separated message per line), so `--method terse` becomes `--report-form terse`.

### Removed

- `pretext import` command (LaTeX conversion via plastex) completely removed. It was an experimental feature that never reached a stable enough state to be useful.
- CodeChat support has been removed. Builds no longer write the `.mapping.json` source-to-output map, `codechat_config.yaml` is no longer a managed project resource (`pretext update-project` deletes an unmodified one), and the devcontainer template no longer forwards the CodeChat Server ports or installs the CodeChat extension. Neither Codespaces nor the PreTeXt Tools VS Code extension use it.
- `pretext validate --dev` (and `--method local-dev`), since validation now always consults the development schema and reports what only the production schema rejects as an experimental construct.
- Ordered-lists as a way to structure multi-part exercises has been deprecated (use `<task>` instead).

## [2.49.1] - 2026-08-13

Includes updates to core through commit: [5836dfc](https://github.com/PreTeXtBook/pretext/commit/5836dfcbdc342841acdbe266871a204c8a9dc8cc)
Expand Down
2 changes: 1 addition & 1 deletion pretext/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

VERSION = get_version("pretext", Path(__file__).parent.parent)

CORE_COMMIT = "5836dfcbdc342841acdbe266871a204c8a9dc8cc"
CORE_COMMIT = "5db49adcff964748dba917941936989e6ca9f09f"


def activate() -> None:
Expand Down
100 changes: 33 additions & 67 deletions pretext/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
resources,
constants,
logger,
plastex,
server,
VERSION,
CORE_COMMIT,
Expand Down Expand Up @@ -735,18 +734,20 @@ def build(
)
@click.argument("target_name", required=False, metavar="target")
@click.option(
"--dev",
is_flag=True,
help="Validate against the development schema (pretext-dev.rng) instead of the "
"stable schema, allowing experimental elements.",
"--method",
type=click.Choice(["local", "server"]),
default="local",
show_default=True,
help='Where the schema checks run: "local" (an installed jing) or "server" '
"(jing as a remote service, needing no local install).",
)
@click.option(
"--method",
type=click.Choice(["local", "local-dev", "server", "terse"]),
default=None,
help='How to validate: "local" (an installed jing, the default), "local-dev" '
'(as "local", against the development schema), "server" (jing as a remote '
'service, needing no local install), or "terse" (machine-readable, one '
"--report-form",
type=click.Choice(["full", "terse"]),
default="full",
show_default=True,
help='The shape of the report: "full" (locations, excerpts, and '
'explanations, meant to be read) or "terse" (machine-readable, one '
"tab-separated message per line).",
)
@click.option(
Expand All @@ -765,18 +766,21 @@ def build(
def validate(
ctx: click.Context,
target_name: Optional[str],
dev: bool,
method: Optional[str],
method: str,
report_form: str,
engine: str,
) -> None:
"""
Validate the source of TARGET against the PreTeXt RelaxNG schema.

Writes the consolidated validation report: the schema messages from jing
together with those of the "validation-plus" stylesheet, each naming the
source file, path, and line it came from. Without TARGET, the first target
in project.ptx is used. Exit codes: 0 = valid, 1 = invalid, 2 = validation
could not be performed (no validator available).
Writes the consolidated validation report: the schema messages from jing,
a survey of the experimental constructs in use, and the messages of the
"validation-plus" stylesheet, each naming the source file, path, and line
it came from. An experimental construct is not an error, so it does not
make validation fail; it is markup whose form may change without a
deprecation cycle. Without TARGET, the first target in project.ptx is used.
Exit codes: 0 = valid, 1 = invalid, 2 = validation could not be performed
(no validator available).
"""
project = ctx.obj["project"]
target = project.get_target(target_name)
Expand All @@ -788,19 +792,19 @@ def validate(
log.error(f"Could not assemble source for validation: {e}")
raise SystemExit(1)

if method is None:
method = "local-dev" if dev else "local"
log.info(
f"Validating source of target {target.name} "
f"(method: {method}, engine: {engine})."
f"(method: {method}, report form: {report_form}, engine: {engine})."
)
if engine == "salve":
log.warning(
"The salve engine is experimental. Its messages are worded "
"differently from jing's, so a report from it will not match a "
"report from jing line for line."
)
result = target.validate_source(method=method, engine=engine)
result = target.validate_source(
method=method, engine=engine, report_form=report_form
)

if result is None:
log.error("Validation could not be performed.")
Expand All @@ -811,7 +815,13 @@ def validate(
)
raise SystemExit(2)

message_count, report = result
message_count, experimental_count, report = result
if experimental_count:
log.info(
f"Experimental constructs are in use at {experimental_count} "
"locations; the report surveys them. They are not errors, but "
"their markup may change without a deprecation cycle."
)
if message_count == 0:
log.info("PreTeXt source passed validation with no messages.")
log.info(f"Report: {report}")
Expand Down Expand Up @@ -1212,47 +1222,3 @@ def deploy(
ctx.invoke(view, stage=True)
else:
project.deploy(update_source=update_source, skip_staging=True, no_push=no_push)


# pretext import
@main.command(
short_help="Experimental: convert a latex file to pretext",
context_settings=CONTEXT_SETTINGS,
name="import",
)
@nice_errors
@click.pass_context
@click.argument("latex_file", required=True)
@click.option("-o", "--output", help="Specify output directory", required=False)
def import_command(ctx: click.Context, latex_file: str, output: str) -> None:
"""
Experimental: convert a latex file to pretext
"""
latex_file_path = Path(latex_file).resolve()
if not latex_file_path.exists():
log.error(f"File {latex_file_path} does not exist.")
return
if output is not None:
output_path = Path(output).resolve()
if not output_path.exists():
log.warning("Output directory does not exist. Creating it.")
output_path.mkdir(parents=True)
else:
output_path = Path.cwd() / "imports" / latex_file_path.stem
output_path.mkdir(parents=True, exist_ok=True)
# Now we use plastex to convert:
log.info(f"Converting {latex_file_path} to PreTeXt.")
with tempfile.TemporaryDirectory(prefix="ptxcli_") as tmpdirname:
temp_path = Path(tmpdirname) / "import"
temp_path.mkdir()
log.info(f"Using temporary directory {temp_path}")
# change to this directory to run plastex
with utils.working_directory(temp_path):
try:
plastex.convert(latex_file_path, output_path)
shutil.copytree(temp_path, output_path, dirs_exist_ok=True)
log.debug(f"Conversion done in {temp_path}")
except Exception as e:
log.error(e)
log.debug("Exception info:\n------------------------\n", exc_info=True)
return
128 changes: 0 additions & 128 deletions pretext/codechat.py

This file was deleted.

2 changes: 1 addition & 1 deletion pretext/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,6 @@

PROJECT_RESOURCES = {
"project.ptx": Path("project.ptx"),
"codechat_config.yaml": Path("codechat_config.yaml"),
".gitignore": Path(".gitignore"),
"devcontainer.json": Path(".devcontainer/devcontainer.json"),
"requirements.txt": Path("requirements.txt"),
Expand All @@ -292,6 +291,7 @@
}

DEPRECATED_PROJECT_RESOURCES = {
"codechat_config.yaml": Path("codechat_config.yaml"),
"deploy.yml": Path(".github", "workflows", "deploy.yml"),
"test-build.yml": Path(".github", "workflows", "test-build.yml"),
".devcontainer.json": Path(".devcontainer.json"),
Expand Down
24 changes: 0 additions & 24 deletions pretext/plastex/Alignment.jinja2s

This file was deleted.

15 changes: 0 additions & 15 deletions pretext/plastex/Arrays.jinja2s

This file was deleted.

15 changes: 0 additions & 15 deletions pretext/plastex/Bibliography.jinja2s

This file was deleted.

Loading