mystmd 1.3.6__tar.gz → 1.3.8__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.6 → mystmd-1.3.8}/PKG-INFO +3 -1
- {mystmd-1.3.6 → mystmd-1.3.8}/_package.json +2 -2
- {mystmd-1.3.6 → mystmd-1.3.8}/pyproject.toml +20 -1
- mystmd-1.3.8/src/mystmd_py/main.py +151 -0
- {mystmd-1.3.6 → mystmd-1.3.8}/src/mystmd_py/myst.cjs +37 -28
- mystmd-1.3.8/src/mystmd_py/nodeenv.py +76 -0
- mystmd-1.3.6/src/mystmd_py/main.py +0 -46
- {mystmd-1.3.6 → mystmd-1.3.8}/.gitignore +0 -0
- {mystmd-1.3.6 → mystmd-1.3.8}/LICENSE +0 -0
- {mystmd-1.3.6 → mystmd-1.3.8}/README.md +0 -0
- {mystmd-1.3.6 → mystmd-1.3.8}/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.8
|
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.8",
|
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.8"
|
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.8";
|
193566
193566
|
var version_default = version;
|
193567
193567
|
|
193568
193568
|
// ../myst-cli/dist/build/build.js
|
@@ -280389,7 +280389,7 @@ function runDirectives(state) {
|
|
280389
280389
|
directiveOpen.map = map14;
|
280390
280390
|
directiveOpen.meta = {
|
280391
280391
|
arg: arg2,
|
280392
|
-
options:
|
280392
|
+
options: getDirectiveOptions(options),
|
280393
280393
|
// Tightness is computed for all directives (are they separated by a newline before/after)
|
280394
280394
|
tight: computeBlockTightness(state.src, token.map)
|
280395
280395
|
};
|
@@ -280471,7 +280471,7 @@ function parseDirectiveContent(content3, info, state) {
|
|
280471
280471
|
const match3 = COLON_OPTION_REGEX.exec(line2);
|
280472
280472
|
const { option: option3, value } = (_a6 = match3 === null || match3 === void 0 ? void 0 : match3.groups) !== null && _a6 !== void 0 ? _a6 : {};
|
280473
280473
|
if (option3)
|
280474
|
-
options.push([option3, value ||
|
280474
|
+
options.push([option3, value || true]);
|
280475
280475
|
bodyOffset++;
|
280476
280476
|
}
|
280477
280477
|
}
|
@@ -280482,31 +280482,28 @@ function parseDirectiveContent(content3, info, state) {
|
|
280482
280482
|
function directiveArgToTokens(arg2, lineNumber, state) {
|
280483
280483
|
return nestedPartToTokens("directive_arg", arg2, lineNumber, state, "run_directives", true);
|
280484
280484
|
}
|
280485
|
-
function
|
280485
|
+
function getDirectiveOptions(options) {
|
280486
280486
|
if (!options)
|
280487
280487
|
return void 0;
|
280488
280488
|
const simplified = {};
|
280489
280489
|
options.forEach(([key2, val]) => {
|
280490
280490
|
if (simplified[key2] !== void 0) {
|
280491
280491
|
return;
|
280492
|
-
} else if (!isNaN(Number(val))) {
|
280493
|
-
simplified[key2] = Number(val);
|
280494
|
-
} else if (typeof val === "string" && val.toLowerCase() === "true") {
|
280495
|
-
simplified[key2] = true;
|
280496
|
-
} else if (typeof val === "string" && val.toLowerCase() === "false") {
|
280497
|
-
simplified[key2] = false;
|
280498
|
-
} else {
|
280499
|
-
simplified[key2] = val;
|
280500
280492
|
}
|
280493
|
+
simplified[key2] = val;
|
280501
280494
|
});
|
280502
280495
|
return simplified;
|
280503
280496
|
}
|
280504
280497
|
function directiveOptionsToTokens(options, lineNumber, state) {
|
280505
280498
|
const tokens = options.map(([key2, value], index4) => {
|
280506
|
-
const optTokens = nestedPartToTokens("directive_option",
|
280499
|
+
const optTokens = typeof value === "string" ? nestedPartToTokens("directive_option", value, lineNumber + index4, state, "run_directives", true) : [
|
280500
|
+
new state.Token("directive_option_open", "", 1),
|
280501
|
+
new state.Token("directive_option_close", "", -1)
|
280502
|
+
];
|
280507
280503
|
if (optTokens.length) {
|
280508
280504
|
optTokens[0].info = key2;
|
280509
|
-
optTokens[0].content = value;
|
280505
|
+
optTokens[0].content = typeof value === "string" ? value : "";
|
280506
|
+
optTokens[0].meta = { value };
|
280510
280507
|
}
|
280511
280508
|
return optTokens;
|
280512
280509
|
});
|
@@ -287928,7 +287925,7 @@ var defaultMdast = {
|
|
287928
287925
|
getAttrs(t2) {
|
287929
287926
|
return {
|
287930
287927
|
name: t2.info,
|
287931
|
-
value: t2.
|
287928
|
+
value: t2.meta.value
|
287932
287929
|
};
|
287933
287930
|
}
|
287934
287931
|
},
|
@@ -288129,6 +288126,8 @@ function contentFromNode(node3, spec, vfile2, description, ruleId) {
|
|
288129
288126
|
return void 0;
|
288130
288127
|
}
|
288131
288128
|
if (spec.type === ParseTypesEnum.string || spec.type === String) {
|
288129
|
+
if (value === true)
|
288130
|
+
return "";
|
288132
288131
|
if (typeof value !== "string" && !(value && typeof value === "number" && !isNaN(value))) {
|
288133
288132
|
fileWarn(vfile2, `value is not a string for ${description}`, { node: node3, ruleId });
|
288134
288133
|
}
|
@@ -288136,7 +288135,7 @@ function contentFromNode(node3, spec, vfile2, description, ruleId) {
|
|
288136
288135
|
}
|
288137
288136
|
if (spec.type === ParseTypesEnum.number || spec.type === Number) {
|
288138
288137
|
const valueAsNumber = Number(value);
|
288139
|
-
if (isNaN(valueAsNumber)) {
|
288138
|
+
if (value === true || isNaN(valueAsNumber)) {
|
288140
288139
|
const fileFn = spec.required ? fileError : fileWarn;
|
288141
288140
|
fileFn(vfile2, `number not provided for ${description}`, { node: node3, ruleId });
|
288142
288141
|
return void 0;
|
@@ -288471,17 +288470,22 @@ var cardDirective = {
|
|
288471
288470
|
name: "card",
|
288472
288471
|
alias: ["grid-item-card"],
|
288473
288472
|
arg: {
|
288474
|
-
type: "myst"
|
288473
|
+
type: "myst",
|
288474
|
+
doc: "The title of the card, usually shown as bolded text at the top of the card."
|
288475
288475
|
},
|
288476
288476
|
options: {
|
288477
|
-
|
288478
|
-
type: String
|
288477
|
+
url: {
|
288478
|
+
type: String,
|
288479
|
+
alias: ["link"],
|
288480
|
+
doc: "Turns the card into a link, can be internal or external."
|
288479
288481
|
},
|
288480
288482
|
header: {
|
288481
|
-
type: "myst"
|
288483
|
+
type: "myst",
|
288484
|
+
doc: "Adds a header to the card."
|
288482
288485
|
},
|
288483
288486
|
footer: {
|
288484
|
-
type: "myst"
|
288487
|
+
type: "myst",
|
288488
|
+
doc: "Adds a footer to the card."
|
288485
288489
|
}
|
288486
288490
|
// // https://sphinx-design.readthedocs.io/en/furo-theme/cards.html#card-options
|
288487
288491
|
// width
|
@@ -288512,10 +288516,11 @@ var cardDirective = {
|
|
288512
288516
|
},
|
288513
288517
|
body: {
|
288514
288518
|
type: "myst",
|
288515
|
-
required: true
|
288519
|
+
required: true,
|
288520
|
+
doc: "Main body content of the card."
|
288516
288521
|
},
|
288517
288522
|
run(data) {
|
288518
|
-
const {
|
288523
|
+
const { url, header, footer: footer2 } = data.options || {};
|
288519
288524
|
let headerChildren;
|
288520
288525
|
let bodyChildren;
|
288521
288526
|
let footerChildren;
|
@@ -288552,7 +288557,7 @@ var cardDirective = {
|
|
288552
288557
|
return [
|
288553
288558
|
{
|
288554
288559
|
type: "card",
|
288555
|
-
url
|
288560
|
+
url,
|
288556
288561
|
children
|
288557
288562
|
}
|
288558
288563
|
];
|
@@ -289038,7 +289043,7 @@ var import_node_path15 = __toESM(require("path"), 1);
|
|
289038
289043
|
var import_nbtx = __toESM(require_cjs2(), 1);
|
289039
289044
|
|
289040
289045
|
// ../myst-cli/dist/version.js
|
289041
|
-
var version2 = "1.3.
|
289046
|
+
var version2 = "1.3.8";
|
289042
289047
|
var version_default2 = version2;
|
289043
289048
|
|
289044
289049
|
// ../myst-cli/dist/utils/headers.js
|
@@ -302319,13 +302324,13 @@ function applyComputedOutputsToNodes(nodes, computedResult) {
|
|
302319
302324
|
async function kernelExecutionTransform(tree, vfile2, opts) {
|
302320
302325
|
var _a6;
|
302321
302326
|
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
|
-
}
|
302325
302327
|
const executableNodes = selectAll(`block[kind=${NotebookCell.code}],inlineExpression`, tree);
|
302326
302328
|
if (executableNodes.length === 0) {
|
302327
302329
|
return;
|
302328
302330
|
}
|
302331
|
+
if (opts.frontmatter.kernelspec === void 0) {
|
302332
|
+
return fileError(vfile2, `Notebook does not declare the necessary 'kernelspec' frontmatter key required for execution`);
|
302333
|
+
}
|
302329
302334
|
const cacheKey = buildCacheKey(opts.frontmatter.kernelspec, executableNodes);
|
302330
302335
|
let cachedResults = opts.cache.get(cacheKey);
|
302331
302336
|
if (opts.ignoreCache || cachedResults === void 0) {
|
@@ -304400,6 +304405,10 @@ var ENVIRONMENTS2 = [
|
|
304400
304405
|
];
|
304401
304406
|
var RE_OPEN2 = new RegExp(`^\\\\begin{(${ENVIRONMENTS2.join("|")})([*]?)}`);
|
304402
304407
|
function isAmsmathEnvironment(value) {
|
304408
|
+
const matches4 = value.trim().matchAll(new RegExp(`\\\\begin{(${ENVIRONMENTS2.join("|")})}`, "g"));
|
304409
|
+
if ([...matches4].length > 1) {
|
304410
|
+
return false;
|
304411
|
+
}
|
304403
304412
|
const matchOpen = value.trim().match(RE_OPEN2);
|
304404
304413
|
if (!matchOpen)
|
304405
304414
|
return false;
|
@@ -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
|