mystmd 1.3.5__tar.gz → 1.3.7__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.
- {mystmd-1.3.5 → mystmd-1.3.7}/PKG-INFO +3 -1
- {mystmd-1.3.5 → mystmd-1.3.7}/_package.json +2 -2
- {mystmd-1.3.5 → mystmd-1.3.7}/pyproject.toml +20 -1
- mystmd-1.3.7/src/mystmd_py/main.py +151 -0
- {mystmd-1.3.5 → mystmd-1.3.7}/src/mystmd_py/myst.cjs +57 -26
- mystmd-1.3.7/src/mystmd_py/nodeenv.py +76 -0
- mystmd-1.3.5/src/mystmd_py/main.py +0 -46
- {mystmd-1.3.5 → mystmd-1.3.7}/.gitignore +0 -0
- {mystmd-1.3.5 → mystmd-1.3.7}/LICENSE +0 -0
- {mystmd-1.3.5 → mystmd-1.3.7}/README.md +0 -0
- {mystmd-1.3.5 → mystmd-1.3.7}/src/mystmd_py/__init__.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: mystmd
|
3
|
-
Version: 1.3.
|
3
|
+
Version: 1.3.7
|
4
4
|
Summary: Command line tools for MyST Markdown
|
5
5
|
Project-URL: Homepage, https://github.com/jupyter-book/mystmd
|
6
6
|
Project-URL: Bug Tracker, https://github.com/jupyter-book/mystmd/issues
|
@@ -21,6 +21,8 @@ Classifier: Programming Language :: Python :: 3.11
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.12
|
22
22
|
Classifier: Topic :: Scientific/Engineering
|
23
23
|
Requires-Python: >=3.8
|
24
|
+
Requires-Dist: platformdirs~=4.2.2
|
25
|
+
Requires-Dist: nodeenv~=1.9.1
|
24
26
|
Provides-Extra: execute
|
25
27
|
Requires-Dist: ipykernel; extra == 'execute'
|
26
28
|
Requires-Dist: jupyter-server; extra == 'execute'
|
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "mystmd",
|
3
|
-
"version": "1.3.
|
3
|
+
"version": "1.3.7",
|
4
4
|
"description": "Command line tools for MyST Markdown",
|
5
5
|
"author": "Rowan Cockett <rowan@curvenote.com>",
|
6
6
|
"license": "MIT",
|
@@ -45,6 +45,6 @@
|
|
45
45
|
"commander": "^10.0.1",
|
46
46
|
"core-js": "^3.31.1",
|
47
47
|
"js-yaml": "^4.1.0",
|
48
|
-
"myst-cli": "^1.3.
|
48
|
+
"myst-cli": "^1.3.7"
|
49
49
|
}
|
50
50
|
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
[build-system]
|
2
|
-
requires = ["hatchling", "hatch-nodejs-version"]
|
2
|
+
requires = ["hatchling", "hatch-nodejs-version", "hatch-deps-selector"]
|
3
3
|
build-backend = "hatchling.build"
|
4
4
|
|
5
5
|
[project]
|
@@ -34,6 +34,25 @@ myst = "mystmd_py.main:main"
|
|
34
34
|
source = "nodejs"
|
35
35
|
path = "_package.json"
|
36
36
|
|
37
|
+
[tool.hatch.build.hooks.selector]
|
38
|
+
default-variant = "pypi"
|
39
|
+
# Name of the env-var that controls which `selector.variants` entry
|
40
|
+
# is used
|
41
|
+
env-var = "MYSTMD_PACKAGE_VARIANT"
|
42
|
+
|
43
|
+
# Ensure that we only bring in nodeenv for PyPI
|
44
|
+
[tool.hatch.build.hooks.selector.variants.pypi]
|
45
|
+
dependencies = [
|
46
|
+
"platformdirs~=4.2.2",
|
47
|
+
"nodeenv~=1.9.1"
|
48
|
+
]
|
49
|
+
|
50
|
+
# Conda-forge has no additional dependencies to the `project.dependencies`
|
51
|
+
# This section is not needed (the env-var can be set to "")
|
52
|
+
# But this makes it more explicit
|
53
|
+
[tool.hatch.build.hooks.selector.variants.conda-forge]
|
54
|
+
dependencies = []
|
55
|
+
|
37
56
|
[tool.hatch.metadata.hooks.nodejs]
|
38
57
|
fields = ["description", "authors", "urls", "keywords", "license"]
|
39
58
|
path = "_package.json"
|
@@ -0,0 +1,151 @@
|
|
1
|
+
import os
|
2
|
+
import pathlib
|
3
|
+
import platform
|
4
|
+
import shutil
|
5
|
+
import subprocess
|
6
|
+
import sys
|
7
|
+
import re
|
8
|
+
import textwrap
|
9
|
+
|
10
|
+
|
11
|
+
NODEENV_VERSION = "18.0.0"
|
12
|
+
INSTALL_NODEENV_KEY = "MYSTMD_ALLOW_NODEENV"
|
13
|
+
|
14
|
+
|
15
|
+
class PermissionDeniedError(Exception): ...
|
16
|
+
|
17
|
+
|
18
|
+
class NodeEnvCreationError(Exception): ...
|
19
|
+
|
20
|
+
|
21
|
+
def is_windows():
|
22
|
+
return platform.system() == "Windows"
|
23
|
+
|
24
|
+
|
25
|
+
def find_installed_node():
|
26
|
+
# shutil.which can find things with PATHEXT, but 3.12.0 breaks this by preferring NODE over NODE.EXE on Windows
|
27
|
+
return shutil.which("node.exe") if is_windows() else shutil.which("node")
|
28
|
+
|
29
|
+
|
30
|
+
def find_nodeenv_path():
|
31
|
+
# The conda packaging of this package does not need to install node!
|
32
|
+
import platformdirs
|
33
|
+
|
34
|
+
return platformdirs.user_data_path(
|
35
|
+
appname="myst", appauthor=False, version=NODEENV_VERSION
|
36
|
+
)
|
37
|
+
|
38
|
+
|
39
|
+
def ask_to_install_node(path):
|
40
|
+
if env_value := os.environ.get(INSTALL_NODEENV_KEY, "").lower():
|
41
|
+
return env_value in {"yes", "true", "1", "y"}
|
42
|
+
|
43
|
+
return input(f"❔ Install Node.js in '{path}'? (y/N): ").lower() == "y"
|
44
|
+
|
45
|
+
|
46
|
+
def create_nodeenv(env_path):
|
47
|
+
command = [
|
48
|
+
sys.executable,
|
49
|
+
"-m",
|
50
|
+
"nodeenv",
|
51
|
+
"-v",
|
52
|
+
f"--node={NODEENV_VERSION}",
|
53
|
+
"--prebuilt",
|
54
|
+
"--clean-src",
|
55
|
+
env_path,
|
56
|
+
]
|
57
|
+
result = subprocess.run(command, capture_output=True, encoding="utf-8")
|
58
|
+
if result.returncode:
|
59
|
+
shutil.rmtree(env_path)
|
60
|
+
raise NodeEnvCreationError(result.stderr)
|
61
|
+
else:
|
62
|
+
return env_path
|
63
|
+
|
64
|
+
|
65
|
+
def find_any_node(binary_path):
|
66
|
+
node_path = find_installed_node()
|
67
|
+
if node_path is not None:
|
68
|
+
return pathlib.Path(node_path).absolute(), binary_path
|
69
|
+
|
70
|
+
nodeenv_path = find_nodeenv_path()
|
71
|
+
if not nodeenv_path.exists():
|
72
|
+
print("❗ Node.js (node) is required to run MyST, but could not be found`.")
|
73
|
+
if ask_to_install_node(nodeenv_path):
|
74
|
+
print(f"⚙️ Attempting to install Node.js in {nodeenv_path} ...")
|
75
|
+
create_nodeenv(nodeenv_path)
|
76
|
+
print(f"ℹ️ Successfully installed Node.js {NODEENV_VERSION}")
|
77
|
+
else:
|
78
|
+
raise PermissionDeniedError("Node.js installation was not permitted")
|
79
|
+
|
80
|
+
# Find the executable path
|
81
|
+
new_node_path = (
|
82
|
+
(nodeenv_path / "Scripts" / "node.exe")
|
83
|
+
if is_windows()
|
84
|
+
else (nodeenv_path / "bin" / "node")
|
85
|
+
)
|
86
|
+
new_path = os.pathsep.join(
|
87
|
+
[*binary_path.split(os.pathsep), str(new_node_path.parent)]
|
88
|
+
)
|
89
|
+
return new_node_path, new_path
|
90
|
+
|
91
|
+
|
92
|
+
def main():
|
93
|
+
# Find NodeJS (and potential new PATH)
|
94
|
+
binary_path = os.environ.get("PATH", os.defpath)
|
95
|
+
try:
|
96
|
+
node_path, os_path = find_any_node(binary_path)
|
97
|
+
except NodeEnvCreationError as err:
|
98
|
+
message = textwrap.indent(err.args[0], " ")
|
99
|
+
raise SystemExit(
|
100
|
+
"💥 The attempt to install Node.js was unsuccessful.\n"
|
101
|
+
f"🔍 Underlying error:\n{message}\n\n"
|
102
|
+
"ℹ️ We recommend installing the latest LTS release, using your preferred package manager "
|
103
|
+
"or following instructions here: https://nodejs.org\n\n"
|
104
|
+
) from err
|
105
|
+
except PermissionDeniedError as err:
|
106
|
+
raise SystemExit(
|
107
|
+
"💥 The attempt to install Node.js failed because the user denied the request.\n"
|
108
|
+
"ℹ️ We recommend installing the latest LTS release, using your preferred package manager "
|
109
|
+
"or following instructions here: https://nodejs.org\n\n"
|
110
|
+
) from err
|
111
|
+
|
112
|
+
# Build new env dict
|
113
|
+
node_env = {**os.environ, "PATH": os_path}
|
114
|
+
|
115
|
+
# Check version
|
116
|
+
_version = subprocess.run(
|
117
|
+
[node_path, "-v"], capture_output=True, check=True, text=True, env=node_env
|
118
|
+
).stdout
|
119
|
+
major_version_match = re.match(r"v(\d+).*", _version)
|
120
|
+
|
121
|
+
if major_version_match is None:
|
122
|
+
raise SystemExit(f"MyST could not determine the version of Node.js: {_version}")
|
123
|
+
major_version = int(major_version_match[1])
|
124
|
+
if not (major_version in {18, 20, 22} or major_version > 22):
|
125
|
+
raise SystemExit(
|
126
|
+
f"MyST requires node 18, 20, or 22+; you are running node {major_version}.\n\n"
|
127
|
+
"Please update to the latest LTS release, using your preferred package manager\n"
|
128
|
+
"or following instructions here: https://nodejs.org/en/download"
|
129
|
+
)
|
130
|
+
|
131
|
+
# Find path to compiled JS
|
132
|
+
js_path = (pathlib.Path(__file__).parent / "myst.cjs").resolve()
|
133
|
+
|
134
|
+
# Build args for Node.js process
|
135
|
+
myst_node_args = [js_path, *sys.argv[1:]]
|
136
|
+
myst_env = {**node_env, "MYST_LANG": "PYTHON"}
|
137
|
+
|
138
|
+
# Invoke appropriate binary for platform
|
139
|
+
if platform.system() == "Windows":
|
140
|
+
result = subprocess.run([node_path, *myst_node_args], env=myst_env)
|
141
|
+
sys.exit(result.returncode)
|
142
|
+
else:
|
143
|
+
os.execve(
|
144
|
+
node_path,
|
145
|
+
[node_path.name, *myst_node_args],
|
146
|
+
myst_env,
|
147
|
+
)
|
148
|
+
|
149
|
+
|
150
|
+
if __name__ == "__main__":
|
151
|
+
main()
|
@@ -193562,7 +193562,7 @@ var {
|
|
193562
193562
|
} = import_index.default;
|
193563
193563
|
|
193564
193564
|
// src/version.ts
|
193565
|
-
var version = "1.3.
|
193565
|
+
var version = "1.3.7";
|
193566
193566
|
var version_default = version;
|
193567
193567
|
|
193568
193568
|
// ../myst-cli/dist/build/build.js
|
@@ -195821,21 +195821,35 @@ function validateJupytext(input3, opts) {
|
|
195821
195821
|
}
|
195822
195822
|
|
195823
195823
|
// ../myst-frontmatter/dist/kernelspec/validators.js
|
195824
|
-
var KERNELSPEC_KEYS = ["name", "
|
195824
|
+
var KERNELSPEC_KEYS = ["name", "display_name", "language", "argv", "env"];
|
195825
195825
|
function validateKernelSpec(input3, opts) {
|
195826
195826
|
const value = validateObjectKeys(input3, { optional: KERNELSPEC_KEYS }, opts);
|
195827
195827
|
if (value === void 0)
|
195828
195828
|
return void 0;
|
195829
|
-
|
195829
|
+
let name3;
|
195830
195830
|
if (defined(value.name)) {
|
195831
|
-
|
195831
|
+
const validatedName = validateString(value.name, incrementOptions("name", opts));
|
195832
|
+
if (validatedName === void 0)
|
195833
|
+
return void 0;
|
195834
|
+
name3 = validatedName;
|
195835
|
+
} else {
|
195836
|
+
name3 = "python3";
|
195837
|
+
validationWarning(`"name" key is required; using '${name3}' as placeholder value`, opts);
|
195838
|
+
}
|
195839
|
+
let displayName;
|
195840
|
+
if (defined(value.display_name)) {
|
195841
|
+
const validatedDisplayName = validateString(value.display_name, incrementOptions("display_name", opts));
|
195842
|
+
if (validatedDisplayName === void 0)
|
195843
|
+
return void 0;
|
195844
|
+
displayName = validatedDisplayName;
|
195845
|
+
} else {
|
195846
|
+
displayName = `${name3} Kernel`;
|
195847
|
+
validationWarning(`"display_name" key is required; using '${displayName}' as placeholder value`, opts);
|
195832
195848
|
}
|
195849
|
+
const output2 = { name: name3, display_name: displayName };
|
195833
195850
|
if (defined(value.language)) {
|
195834
195851
|
output2.language = validateString(value.language, incrementOptions("language", opts));
|
195835
195852
|
}
|
195836
|
-
if (defined(value.display_name)) {
|
195837
|
-
output2.display_name = validateString(value.display_name, incrementOptions("display_name", opts));
|
195838
|
-
}
|
195839
195853
|
if (defined(value.env)) {
|
195840
195854
|
output2.env = validateObject(value.env, incrementOptions("env", opts));
|
195841
195855
|
}
|
@@ -241223,9 +241237,12 @@ function addWarningForFile(session, file, message, severity = "warn", opts) {
|
|
241223
241237
|
session.log.error(`\u26D4\uFE0F ${prefix2}${formatted}`);
|
241224
241238
|
break;
|
241225
241239
|
case "warn":
|
241226
|
-
default:
|
241227
241240
|
session.log.warn(`\u26A0\uFE0F ${prefix2}${formatted}`);
|
241228
241241
|
break;
|
241242
|
+
case "debug":
|
241243
|
+
default:
|
241244
|
+
session.log.debug(`${prefix2}${formatted}`);
|
241245
|
+
break;
|
241229
241246
|
}
|
241230
241247
|
if (opts === null || opts === void 0 ? void 0 : opts.ruleId) {
|
241231
241248
|
session.log.debug(`To suppress this message, add rule: "${opts.ruleId}"${opts.key ? ` with key: "${opts.key}"` : ""} to "error_rules" in your project config`);
|
@@ -285686,7 +285703,7 @@ var citeRole = {
|
|
285686
285703
|
run(data) {
|
285687
285704
|
const content3 = data.body;
|
285688
285705
|
const labels = content3.split(/[,;]/).map((s5) => s5.trim());
|
285689
|
-
const kind = data.name.startsWith("cite:p") || data.name.includes("par") ? "parenthetical" : "narrative";
|
285706
|
+
const kind = data.name.startsWith("cite:p") || data.name.includes("par") || data.name.includes("cite:alp") ? "parenthetical" : "narrative";
|
285690
285707
|
const children = labels.map((c) => {
|
285691
285708
|
var _a6, _b;
|
285692
285709
|
const groups = /^(?:\{([^{]*)\})?([^{]*)(?:\{([^{]*)\})?$/;
|
@@ -285713,6 +285730,9 @@ var citeRole = {
|
|
285713
285730
|
if (data.name === "cite" && children.length === 1) {
|
285714
285731
|
return children;
|
285715
285732
|
}
|
285733
|
+
if (data.name.includes("cite:alp")) {
|
285734
|
+
return children;
|
285735
|
+
}
|
285716
285736
|
return [
|
285717
285737
|
{
|
285718
285738
|
type: "citeGroup",
|
@@ -289018,7 +289038,7 @@ var import_node_path15 = __toESM(require("path"), 1);
|
|
289018
289038
|
var import_nbtx = __toESM(require_cjs2(), 1);
|
289019
289039
|
|
289020
289040
|
// ../myst-cli/dist/version.js
|
289021
|
-
var version2 = "1.3.
|
289041
|
+
var version2 = "1.3.7";
|
289022
289042
|
var version_default2 = version2;
|
289023
289043
|
|
289024
289044
|
// ../myst-cli/dist/utils/headers.js
|
@@ -289439,7 +289459,7 @@ async function convertImageToWebp(session, image6, { quality = 80, overwrite = f
|
|
289439
289459
|
minimumFractionDigits: 2,
|
289440
289460
|
maximumFractionDigits: 2
|
289441
289461
|
});
|
289442
|
-
addWarningForFile(session, image6, `Image is too large (${inMB} MB) to convert to webp (build will be slow).`, "warn", { ruleId: RuleId.imageFormatOptimizes });
|
289462
|
+
addWarningForFile(session, image6, `Image is too large (${inMB} MB) to convert to webp (build will be slow).`, isGif2webpAvailable() && imageExt === ".gif" || isWebpAvailable() ? "warn" : "debug", { ruleId: RuleId.imageFormatOptimizes });
|
289443
289463
|
return null;
|
289444
289464
|
}
|
289445
289465
|
const dirname8 = import_node_path13.default.dirname(image6);
|
@@ -289479,7 +289499,7 @@ imagemagick and cwebp are required
|
|
289479
289499
|
if (!isGif2webpAvailable()) {
|
289480
289500
|
addWarningForFile(session, image6, `Could not convert from image ${image6} to webp:
|
289481
289501
|
gif2webp is required
|
289482
|
-
`, "
|
289502
|
+
`, "debug", { ruleId: RuleId.imageFormatOptimizes });
|
289483
289503
|
return null;
|
289484
289504
|
}
|
289485
289505
|
await convertGif();
|
@@ -289487,7 +289507,7 @@ gif2webp is required
|
|
289487
289507
|
if (!isWebpAvailable()) {
|
289488
289508
|
addWarningForFile(session, image6, `Could not convert from image ${image6} to webp:
|
289489
289509
|
cwebp is required
|
289490
|
-
`, "
|
289510
|
+
`, "debug", { ruleId: RuleId.imageFormatOptimizes });
|
289491
289511
|
return null;
|
289492
289512
|
}
|
289493
289513
|
await convertImg();
|
@@ -302218,7 +302238,7 @@ async function evaluateExpression(kernel, expr) {
|
|
302218
302238
|
(0, import_node_assert.default)(result !== void 0);
|
302219
302239
|
return { status: result.status, result };
|
302220
302240
|
}
|
302221
|
-
function buildCacheKey(nodes) {
|
302241
|
+
function buildCacheKey(kernelSpec, nodes) {
|
302222
302242
|
var _a6, _b, _c;
|
302223
302243
|
const hashableItems = [];
|
302224
302244
|
for (const node3 of nodes) {
|
@@ -302237,8 +302257,7 @@ function buildCacheKey(nodes) {
|
|
302237
302257
|
});
|
302238
302258
|
}
|
302239
302259
|
}
|
302240
|
-
|
302241
|
-
return (0, import_node_crypto4.createHash)("md5").update(hashableString).digest("hex");
|
302260
|
+
return (0, import_node_crypto4.createHash)("md5").update(kernelSpec.name).update(JSON.stringify(hashableItems)).digest("hex");
|
302242
302261
|
}
|
302243
302262
|
function isCellBlock(node3) {
|
302244
302263
|
return node3.type === "block" && select("code", node3) !== null && select("output", node3) !== null;
|
@@ -302298,13 +302317,16 @@ function applyComputedOutputsToNodes(nodes, computedResult) {
|
|
302298
302317
|
}
|
302299
302318
|
}
|
302300
302319
|
async function kernelExecutionTransform(tree, vfile2, opts) {
|
302301
|
-
var _a6
|
302320
|
+
var _a6;
|
302302
302321
|
const log = (_a6 = opts.log) !== null && _a6 !== void 0 ? _a6 : console;
|
302322
|
+
if (opts.frontmatter.kernelspec === void 0) {
|
302323
|
+
return fileError(vfile2, `Notebook does not declare the necessary 'kernelspec' frontmatter key required for execution`);
|
302324
|
+
}
|
302303
302325
|
const executableNodes = selectAll(`block[kind=${NotebookCell.code}],inlineExpression`, tree);
|
302304
302326
|
if (executableNodes.length === 0) {
|
302305
302327
|
return;
|
302306
302328
|
}
|
302307
|
-
const cacheKey = buildCacheKey(executableNodes);
|
302329
|
+
const cacheKey = buildCacheKey(opts.frontmatter.kernelspec, executableNodes);
|
302308
302330
|
let cachedResults = opts.cache.get(cacheKey);
|
302309
302331
|
if (opts.ignoreCache || cachedResults === void 0) {
|
302310
302332
|
log.info(`\u{1F4BF} Executing Notebook (${vfile2.path}) ${opts.ignoreCache ? "[cache ignored]" : "[no execution cache found]"}`);
|
@@ -302320,7 +302342,7 @@ async function kernelExecutionTransform(tree, vfile2, opts) {
|
|
302320
302342
|
type: "notebook",
|
302321
302343
|
name: import_node_path34.default.basename(vfile2.path),
|
302322
302344
|
kernel: {
|
302323
|
-
name:
|
302345
|
+
name: opts.frontmatter.kernelspec.name
|
302324
302346
|
}
|
302325
302347
|
};
|
302326
302348
|
await sessionManager.startNew(sessionOpts).catch((err) => {
|
@@ -323419,14 +323441,21 @@ ${errors4}`);
|
|
323419
323441
|
function assertNever() {
|
323420
323442
|
throw new Error("unreachable code");
|
323421
323443
|
}
|
323422
|
-
function
|
323423
|
-
const
|
323444
|
+
function maybeResolveDocument(dir, name3, session) {
|
323445
|
+
const resolved = resolveExtension((0, import_node_path59.join)(dir, name3));
|
323446
|
+
if (resolved) {
|
323447
|
+
return (0, import_node_path59.relative)(dir, resolved);
|
323448
|
+
}
|
323449
|
+
session.log.error(`Could not find a file named ${name3} (declared in table of contents)`);
|
323450
|
+
return name3;
|
323451
|
+
}
|
323452
|
+
function convertNoFormat(session, dir, data) {
|
323453
|
+
const rootEntry = { file: maybeResolveDocument(dir, data.root, session) };
|
323424
323454
|
const convertEntry = (item) => {
|
323425
323455
|
let entry;
|
323426
323456
|
if ("file" in item) {
|
323427
|
-
const resolved = resolveExtension((0, import_node_path59.join)(dir, item.file));
|
323428
323457
|
entry = {
|
323429
|
-
file: (
|
323458
|
+
file: maybeResolveDocument(dir, item.file, session),
|
323430
323459
|
title: item.title
|
323431
323460
|
};
|
323432
323461
|
} else if ("url" in item) {
|
@@ -323543,7 +323572,7 @@ function convertArticleToNoFormat(data) {
|
|
323543
323572
|
}
|
323544
323573
|
return result;
|
323545
323574
|
}
|
323546
|
-
function upgradeTOC(data) {
|
323575
|
+
function upgradeTOC(session, data) {
|
323547
323576
|
const dir = (0, import_node_process6.cwd)();
|
323548
323577
|
let dataNoFormat;
|
323549
323578
|
if ("format" in data) {
|
@@ -323562,7 +323591,7 @@ function upgradeTOC(data) {
|
|
323562
323591
|
} else {
|
323563
323592
|
dataNoFormat = data;
|
323564
323593
|
}
|
323565
|
-
return convertNoFormat(dir, dataNoFormat);
|
323594
|
+
return convertNoFormat(session, dir, dataNoFormat);
|
323566
323595
|
}
|
323567
323596
|
|
323568
323597
|
// ../myst-cli/dist/init/jupyter-book/syntax.js
|
@@ -323758,13 +323787,15 @@ async function upgradeJupyterBook(session, configFile) {
|
|
323758
323787
|
const configContent = await import_promises4.default.readFile("_config.yml", { encoding: "utf-8" });
|
323759
323788
|
const configData2 = validateJupyterBookConfig(js_yaml_default.load(configContent));
|
323760
323789
|
if (defined2(configData2)) {
|
323790
|
+
session.log.info(`Migrating Jupyter Book configuration to ${source_default.blue("myst.yml")}`);
|
323761
323791
|
({ site: config3.site, project: config3.project } = upgradeConfig(configData2));
|
323762
323792
|
}
|
323763
323793
|
if (await fsExists("_toc.yml")) {
|
323764
323794
|
const tocContent = await import_promises4.default.readFile("_toc.yml", { encoding: "utf-8" });
|
323765
323795
|
const tocData = validateSphinxExternalTOC(js_yaml_default.load(tocContent));
|
323766
323796
|
if (defined2(tocData)) {
|
323767
|
-
|
323797
|
+
session.log.info(`Migrating TOC to ${source_default.blue("myst.yml")}`);
|
323798
|
+
config3.project.toc = upgradeTOC(session, tocData);
|
323768
323799
|
}
|
323769
323800
|
}
|
323770
323801
|
await upgradeProjectSyntax(session);
|
@@ -0,0 +1,76 @@
|
|
1
|
+
import os
|
2
|
+
import pathlib
|
3
|
+
import shutil
|
4
|
+
import subprocess
|
5
|
+
import sys
|
6
|
+
|
7
|
+
|
8
|
+
NODEENV_VERSION = "18.0.0"
|
9
|
+
INSTALL_NODEENV_KEY = "MYSTMD_ALLOW_NODEENV"
|
10
|
+
|
11
|
+
|
12
|
+
class PermissionDeniedError(Exception): ...
|
13
|
+
|
14
|
+
|
15
|
+
class NodeEnvCreationError(Exception): ...
|
16
|
+
|
17
|
+
|
18
|
+
def find_installed_node():
|
19
|
+
return shutil.which("node") or shutil.which("node.exe") or shutil.which("node.cmd")
|
20
|
+
|
21
|
+
|
22
|
+
def find_nodeenv_path():
|
23
|
+
# The conda packaging of this package does not need to install node!
|
24
|
+
import platformdirs
|
25
|
+
return platformdirs.user_data_path(
|
26
|
+
appname="myst", appauthor=False, version=NODEENV_VERSION
|
27
|
+
)
|
28
|
+
|
29
|
+
|
30
|
+
def ask_to_install_node(path):
|
31
|
+
if env_value := os.environ.get(INSTALL_NODEENV_KEY, "").lower():
|
32
|
+
return env_value in {"yes", "true", "1", "y"}
|
33
|
+
|
34
|
+
return input(f"❔ Install Node.js in '{path}'? (y/N): ").lower() == "y"
|
35
|
+
|
36
|
+
|
37
|
+
def create_nodeenv(env_path):
|
38
|
+
command = [
|
39
|
+
sys.executable,
|
40
|
+
"-m",
|
41
|
+
"nodeenv",
|
42
|
+
"-v",
|
43
|
+
f"--node={NODEENV_VERSION}",
|
44
|
+
"--prebuilt",
|
45
|
+
"--clean-src",
|
46
|
+
env_path,
|
47
|
+
]
|
48
|
+
result = subprocess.run(command, capture_output=True, encoding="utf-8")
|
49
|
+
if result.returncode:
|
50
|
+
shutil.rmtree(env_path)
|
51
|
+
raise NodeEnvCreationError(result.stderr)
|
52
|
+
else:
|
53
|
+
return env_path
|
54
|
+
|
55
|
+
|
56
|
+
def find_any_node(binary_path):
|
57
|
+
node_path = find_installed_node()
|
58
|
+
if node_path is not None:
|
59
|
+
return pathlib.Path(node_path).absolute(), binary_path
|
60
|
+
|
61
|
+
nodeenv_path = find_nodeenv_path()
|
62
|
+
if not nodeenv_path.exists():
|
63
|
+
print("❗ Node.js (node) is required to run MyST, but could not be found`.")
|
64
|
+
if ask_to_install_node(nodeenv_path):
|
65
|
+
print(f"⚙️ Attempting to install Node.js in {nodeenv_path} ...")
|
66
|
+
create_nodeenv(nodeenv_path)
|
67
|
+
print(f"ℹ️ Successfully installed Node.js {NODEENV_VERSION}")
|
68
|
+
else:
|
69
|
+
raise PermissionDeniedError("Node.js installation was not permitted")
|
70
|
+
|
71
|
+
new_path = os.pathsep.join(
|
72
|
+
[*binary_path.split(os.pathsep), str(nodeenv_path / "bin")]
|
73
|
+
)
|
74
|
+
return nodeenv_path / "bin" / "node", new_path
|
75
|
+
|
76
|
+
|
@@ -1,46 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
import pathlib
|
3
|
-
import shutil
|
4
|
-
import subprocess
|
5
|
-
import sys
|
6
|
-
import re
|
7
|
-
|
8
|
-
|
9
|
-
def main():
|
10
|
-
NODE_LOCATION = (
|
11
|
-
shutil.which("node") or shutil.which("node.exe") or shutil.which("node.cmd")
|
12
|
-
)
|
13
|
-
PATH_TO_BIN_JS = (pathlib.Path(__file__).parent / "myst.cjs").resolve()
|
14
|
-
|
15
|
-
if not NODE_LOCATION:
|
16
|
-
raise SystemExit(
|
17
|
-
"You must install node >=18 to run MyST\n\n"
|
18
|
-
"We recommend installing the latest LTS release, using your preferred package manager\n"
|
19
|
-
"or following instructions here: https://nodejs.org/en/download"
|
20
|
-
)
|
21
|
-
node = pathlib.Path(NODE_LOCATION).absolute()
|
22
|
-
|
23
|
-
_version = subprocess.run(
|
24
|
-
[node, "-v"], capture_output=True, check=True, text=True
|
25
|
-
).stdout
|
26
|
-
major_version_match = re.match(r"v(\d+).*", _version)
|
27
|
-
|
28
|
-
if major_version_match is None:
|
29
|
-
raise SystemExit(f"MyST could not determine the version of Node.js: {_version}")
|
30
|
-
|
31
|
-
major_version = int(major_version_match[1])
|
32
|
-
if not (major_version in {18, 20, 22} or major_version > 22):
|
33
|
-
raise SystemExit(
|
34
|
-
f"MyST requires node 18, 20, or 22+; you are running node {major_version}.\n\n"
|
35
|
-
"Please update to the latest LTS release, using your preferred package manager\n"
|
36
|
-
"or following instructions here: https://nodejs.org/en/download"
|
37
|
-
)
|
38
|
-
os.execve(
|
39
|
-
node,
|
40
|
-
[node.name, PATH_TO_BIN_JS, *sys.argv[1:]],
|
41
|
-
{**os.environ, "MYST_LANG": "PYTHON"},
|
42
|
-
)
|
43
|
-
|
44
|
-
|
45
|
-
if __name__ == "__main__":
|
46
|
-
main()
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|