mystmd 1.3.27__tar.gz → 1.4.0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mystmd
3
- Version: 1.3.27
3
+ Version: 1.4.0
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mystmd",
3
- "version": "1.3.27",
3
+ "version": "1.4.0",
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.27"
48
+ "myst-cli": "^1.4.0"
49
49
  }
50
50
  }
@@ -193440,7 +193440,7 @@ var {
193440
193440
  } = import_index.default;
193441
193441
 
193442
193442
  // src/version.ts
193443
- var version = "1.3.27";
193443
+ var version = "1.4.0";
193444
193444
  var version_default = version;
193445
193445
 
193446
193446
  // ../myst-cli/dist/build/build.js
@@ -194047,7 +194047,7 @@ function validateUrl(input3, opts) {
194047
194047
  }
194048
194048
  return value;
194049
194049
  }
194050
- function validateSubdomain(input3, opts) {
194050
+ function validateDomain(input3, opts) {
194051
194051
  let value = validateString(input3, { ...opts, maxLength: 2048 });
194052
194052
  if (value === void 0)
194053
194053
  return value;
@@ -194058,7 +194058,7 @@ function validateSubdomain(input3, opts) {
194058
194058
  try {
194059
194059
  url = new URL(value);
194060
194060
  } catch {
194061
- return validationError(`must be valid domain: ${input3}`, opts);
194061
+ return validationError(`domain must be valid when used as a URL: ${input3}`, opts);
194062
194062
  }
194063
194063
  const { hash, host, pathname, protocol, search: search4 } = url;
194064
194064
  if (protocol !== "http:" && protocol !== "https:") {
@@ -194067,11 +194067,16 @@ function validateSubdomain(input3, opts) {
194067
194067
  if (pathname && pathname !== "/" || hash || search4) {
194068
194068
  return validationError(`must not specify path, query, or fragment: ${input3}`, opts);
194069
194069
  }
194070
- if (!host.match(/^.+\..+\..+$/)) {
194071
- return validationError(`must be a subdomain: ${input3}`, opts);
194072
- }
194070
+ const numParts = host.split(".").length;
194071
+ if (opts.minParts !== void 0 && opts.minParts > numParts)
194072
+ return validationError(`must have at least ${opts.minParts} parts: ${input3}`, opts);
194073
+ if (opts.maxParts !== void 0 && opts.maxParts < numParts)
194074
+ return validationError(`must have at most ${opts.minParts} parts: ${input3}`, opts);
194073
194075
  return host.toLowerCase();
194074
194076
  }
194077
+ function validateSubdomain(input3, opts) {
194078
+ return validateDomain(input3, { ...opts, minParts: 3 });
194079
+ }
194075
194080
  function validateEmail(input3, opts) {
194076
194081
  const value = validateString(input3, opts);
194077
194082
  if (value === void 0)
@@ -194455,7 +194460,7 @@ function validateStringOrNumber(input3, opts) {
194455
194460
  return validationError("must be string or number", opts);
194456
194461
  }
194457
194462
 
194458
- // ../myst-frontmatter/dist/utils/socialLinks.js
194463
+ // ../myst-frontmatter/dist/socials/types.js
194459
194464
  var SOCIAL_LINKS_KEYS = [
194460
194465
  "url",
194461
194466
  "github",
@@ -194463,8 +194468,14 @@ var SOCIAL_LINKS_KEYS = [
194463
194468
  "mastodon",
194464
194469
  "linkedin",
194465
194470
  "threads",
194466
- "twitter"
194471
+ "twitter",
194467
194472
  // Change to 'x' in future
194473
+ "youtube",
194474
+ "discourse",
194475
+ "discord",
194476
+ "slack",
194477
+ "facebook",
194478
+ "telegram"
194468
194479
  ];
194469
194480
  var SOCIAL_LINKS_ALIASES = {
194470
194481
  website: "url",
@@ -194474,30 +194485,171 @@ var SOCIAL_LINKS_ALIASES = {
194474
194485
  instagram: "threads"
194475
194486
  // This is the same username
194476
194487
  };
194477
- function validateSocialLinks(input3, opts, output2 = {}) {
194488
+
194489
+ // ../myst-frontmatter/dist/socials/validators.js
194490
+ var MASTODON_REGEX = /^@?([a-zA-Z0-9_]+)@([^@]+\.[^@]*[^.])$/;
194491
+ var BLUESKY_REGEX = /^@?([^/:]+\..*[^.])$/;
194492
+ var BLUESKY_URL_REGEX = /^https:\/\/bsky\.app\/profile\/@?(.+\..*[^.])$/;
194493
+ var YOUTUBE_REGEX = /^@?([a-zA-Z0-9.]+)$/;
194494
+ var THREADS_REGEX = /^[a-zA-Z0-9_.]+$/;
194495
+ var TWITTER_REGEX = /^@?([a-zA-Z0-9_]{4,15})$/;
194496
+ var TWITTER_URL_REGEX = /^https:\/\/(?:twitter\.com|x\.com)\/@?([a-zA-Z0-9_]{4,15})$/;
194497
+ var GITHUB_USERNAME_REGEX = /^@?([a-zA-Z0-9_.-]+)$/;
194498
+ var GITHUB_ORG_URL_REGEX = /^https:\/\/github\.com\/orgs\/[a-zA-Z0-9_.-]+$/;
194499
+ var TELEGRAM_REGEX = /^@?([a-zA-Z0-9_]{5,})$/;
194500
+ var TELEGRAM_URL_REGEX = /^https:\/\/(?:t\.me|telegram\.me)\/?([a-zA-Z0-9_]{5,})$/;
194501
+ function validateMastodon(input3, opts) {
194502
+ const value = validateString(input3, opts);
194503
+ if (value === void 0)
194504
+ return void 0;
194505
+ const match3 = value.match(MASTODON_REGEX);
194506
+ if (match3 === null)
194507
+ return validationError(`must be a user ID of the form @username@server e.g. @mystmarkdown@fosstodon.org`, opts);
194508
+ const username = match3[1];
194509
+ const host = validateDomain(match3[2], opts);
194510
+ if (host === void 0)
194511
+ return void 0;
194512
+ return `@${username}@${host}`;
194513
+ }
194514
+ function validateBluesky(input3, opts) {
194515
+ const value = validateString(input3, opts);
194516
+ if (value === void 0)
194517
+ return void 0;
194518
+ let match3;
194519
+ if (match3 = value.match(BLUESKY_REGEX)) {
194520
+ const domain = validateDomain(match3[1], opts);
194521
+ if (domain === void 0)
194522
+ return void 0;
194523
+ return `@${domain}`;
194524
+ } else {
194525
+ const result = validateUrl(value, opts);
194526
+ if (result === void 0)
194527
+ return void 0;
194528
+ match3 = result.match(BLUESKY_URL_REGEX);
194529
+ if (match3 === null) {
194530
+ return validationError(`Bluesky profile URL must be a valid URL starting with https://bsky.app/profile/: ${value}`, opts);
194531
+ }
194532
+ const domain = validateDomain(match3[1], opts);
194533
+ if (domain === void 0)
194534
+ return void 0;
194535
+ return `@${domain}`;
194536
+ }
194537
+ }
194538
+ function validateTwitter(input3, opts) {
194539
+ const value = validateString(input3, opts);
194540
+ if (value === void 0)
194541
+ return void 0;
194542
+ let match3;
194543
+ if (match3 = value.match(TWITTER_URL_REGEX)) {
194544
+ return match3[1];
194545
+ } else if (match3 = value.match(TWITTER_REGEX)) {
194546
+ return match3[1];
194547
+ } else {
194548
+ return validationError(`Twitter social identity must be a valid URL starting with https://twitter.com/, https://x.com/, or a valid username: ${value}`, opts);
194549
+ }
194550
+ }
194551
+ function validateTelegram(input3, opts) {
194552
+ const value = validateString(input3, opts);
194553
+ if (value === void 0)
194554
+ return void 0;
194555
+ let match3;
194556
+ if (match3 = value.match(TELEGRAM_URL_REGEX)) {
194557
+ return match3[1];
194558
+ } else if (match3 = value.match(TELEGRAM_REGEX)) {
194559
+ return match3[1];
194560
+ } else {
194561
+ return validationError(`Telegram social identity must be a valid URL starting with either https://t.me/ or https://telegram.me/, or a valid username: ${value}`, opts);
194562
+ }
194563
+ }
194564
+ function validateYouTube(input3, opts) {
194565
+ const value = validateString(input3, opts);
194566
+ if (value === void 0)
194567
+ return void 0;
194568
+ if (/^https?:\/\//.test(value)) {
194569
+ return validateUrl(input3, { ...opts, includes: "youtube.com" });
194570
+ }
194571
+ let match3;
194572
+ if (match3 = value.match(YOUTUBE_REGEX)) {
194573
+ return match3[1];
194574
+ } else {
194575
+ return validationError(`YouTube social identity must be a valid URL starting with https://youtube.com/ or a valid handle: ${value}`, opts);
194576
+ }
194577
+ }
194578
+ function validateGitHub(input3, opts) {
194579
+ const value = validateString(input3, opts);
194580
+ if (value === void 0)
194581
+ return void 0;
194582
+ let match3;
194583
+ if (match3 = value.match(GITHUB_USERNAME_REGEX)) {
194584
+ return match3[1];
194585
+ } else if (match3 = value.match(GITHUB_USERNAME_REPO_REGEX)) {
194586
+ return match3[0];
194587
+ } else if (match3 = value.match(GITHUB_ORG_URL_REGEX)) {
194588
+ return match3[0];
194589
+ } else {
194590
+ return validationError(`GitHub social identity must be a valid username, org/repo, or org URL: ${value}`, opts);
194591
+ }
194592
+ }
194593
+ function validateSocialLinks(input3, opts, output2) {
194478
194594
  const value = output2 ? input3 : validateObjectKeys(input3, { optional: SOCIAL_LINKS_KEYS, alias: SOCIAL_LINKS_ALIASES }, opts);
194595
+ if (value === void 0)
194596
+ return void 0;
194597
+ const result = output2 !== null && output2 !== void 0 ? output2 : {};
194479
194598
  if (defined(value.url)) {
194480
- output2.url = validateUrl(value.url, incrementOptions("url", opts));
194599
+ result.url = validateUrl(value.url, incrementOptions("url", opts));
194481
194600
  }
194482
194601
  if (defined(value.github)) {
194483
- output2.github = validateString(value.github, incrementOptions("github", opts));
194602
+ result.github = validateGitHub(value.github, incrementOptions("github", opts));
194484
194603
  }
194485
194604
  if (defined(value.bluesky)) {
194486
- output2.bluesky = validateString(value.bluesky, incrementOptions("bluesky", opts));
194605
+ result.bluesky = validateBluesky(value.bluesky, incrementOptions("bluesky", opts));
194487
194606
  }
194488
194607
  if (defined(value.mastodon)) {
194489
- output2.mastodon = validateString(value.mastodon, incrementOptions("mastodon", opts));
194608
+ result.mastodon = validateMastodon(value.mastodon, incrementOptions("mastodon", opts));
194490
194609
  }
194491
194610
  if (defined(value.linkedin)) {
194492
- output2.linkedin = validateUrl(value.linkedin, incrementOptions("linkedin", opts));
194611
+ result.linkedin = validateUrl(value.linkedin, {
194612
+ ...incrementOptions("linkedin", opts),
194613
+ includes: "linkedin.com"
194614
+ });
194493
194615
  }
194494
194616
  if (defined(value.threads)) {
194495
- output2.threads = validateString(value.threads, incrementOptions("threads", opts));
194617
+ result.threads = validateString(value.threads, {
194618
+ ...incrementOptions("threads", opts),
194619
+ regex: THREADS_REGEX
194620
+ });
194496
194621
  }
194497
194622
  if (defined(value.twitter)) {
194498
- output2.twitter = validateString(value.twitter, incrementOptions("twitter", opts));
194623
+ result.twitter = validateTwitter(value.twitter, incrementOptions("twitter", opts));
194499
194624
  }
194500
- return output2;
194625
+ if (defined(value.telegram)) {
194626
+ result.telegram = validateTelegram(value.telegram, incrementOptions("telegram", opts));
194627
+ }
194628
+ if (defined(value.youtube)) {
194629
+ result.youtube = validateYouTube(value.youtube, incrementOptions("youtube", opts));
194630
+ }
194631
+ if (defined(value.discourse)) {
194632
+ result.discourse = validateUrl(value.discourse, incrementOptions("discourse", opts));
194633
+ }
194634
+ if (defined(value.discord)) {
194635
+ result.discord = validateUrl(value.discord, {
194636
+ ...incrementOptions("discord", opts),
194637
+ includes: "discord"
194638
+ });
194639
+ }
194640
+ if (defined(value.slack)) {
194641
+ result.slack = validateUrl(value.slack, {
194642
+ ...incrementOptions("slack", opts),
194643
+ includes: "slack.com"
194644
+ });
194645
+ }
194646
+ if (defined(value.facebook)) {
194647
+ result.facebook = validateUrl(value.facebook, {
194648
+ ...incrementOptions("facebook", opts),
194649
+ includes: "facebook.com"
194650
+ });
194651
+ }
194652
+ return result;
194501
194653
  }
194502
194654
 
194503
194655
  // ../myst-frontmatter/dist/affiliations/validators.js
@@ -195102,6 +195254,7 @@ var SITE_FRONTMATTER_KEYS = [
195102
195254
  "copyright",
195103
195255
  "options",
195104
195256
  "parts",
195257
+ "social",
195105
195258
  ...PAGE_KNOWN_PARTS
195106
195259
  ];
195107
195260
  var FRONTMATTER_ALIASES = {
@@ -195131,7 +195284,8 @@ var FRONTMATTER_ALIASES = {
195131
195284
  key_points: "keypoints",
195132
195285
  "key-points": "keypoints",
195133
195286
  image: "thumbnail",
195134
- identifier: "identifiers"
195287
+ identifier: "identifiers",
195288
+ socials: "social"
195135
195289
  };
195136
195290
 
195137
195291
  // ../myst-frontmatter/dist/project/types.js
@@ -199222,6 +199376,9 @@ function validateProjectFrontmatterKeys(value, opts) {
199222
199376
  if (defined(value.toc)) {
199223
199377
  output2.toc = validateTOC(value.toc, incrementOptions("toc", opts));
199224
199378
  }
199379
+ if (defined(value.social)) {
199380
+ output2.social = validateSocialLinks(value.social, incrementOptions("social", opts));
199381
+ }
199225
199382
  if (defined(value.requirements)) {
199226
199383
  output2.requirements = validateList(value.requirements, incrementOptions("requirements", opts), (req, index4) => {
199227
199384
  return validateString(req, incrementOptions(`requirements.${index4}`, opts));
@@ -237461,7 +237618,7 @@ function formatLinkText(link4) {
237461
237618
  if (((_a6 = link4.children) === null || _a6 === void 0 ? void 0 : _a6.length) !== 1 || link4.children[0].type !== "text")
237462
237619
  return;
237463
237620
  const url = link4.children[0].value;
237464
- if (url.length < 20 || url.match(/\s/) || url.startsWith("wiki:"))
237621
+ if (url.length < 20 || url.match(/\s/))
237465
237622
  return;
237466
237623
  if (url.includes("\u200B"))
237467
237624
  return;
@@ -237477,7 +237634,9 @@ function linksTransform(mdast2, file, opts) {
237477
237634
  link4.urlSource = link4.url;
237478
237635
  const transform3 = opts.transformers.find((t2) => t2.test(link4.urlSource));
237479
237636
  const result = transform3 === null || transform3 === void 0 ? void 0 : transform3.transform(link4, file);
237480
- formatLinkText(link4);
237637
+ if (!(transform3 === null || transform3 === void 0 ? void 0 : transform3.formatsText)) {
237638
+ formatLinkText(link4);
237639
+ }
237481
237640
  if (!transform3 || result === void 0)
237482
237641
  return;
237483
237642
  if (result) {
@@ -237692,6 +237851,7 @@ var WikiTransformer = class {
237692
237851
  constructor(opts) {
237693
237852
  var _a6, _b;
237694
237853
  this.protocol = "wiki";
237854
+ this.formatsText = true;
237695
237855
  this.wikiUrl = removeWiki((_a6 = opts === null || opts === void 0 ? void 0 : opts.url) !== null && _a6 !== void 0 ? _a6 : `https://${(opts === null || opts === void 0 ? void 0 : opts.lang) || DEFAULT_LANGUAGE}.wikipedia.org/`, "/");
237696
237856
  this.lang = (opts === null || opts === void 0 ? void 0 : opts.lang) || ((_b = `${this.wikiUrl}wiki/x`.match(ANY_WIKIPEDIA_ORG)) === null || _b === void 0 ? void 0 : _b[1]) || void 0;
237697
237857
  }
@@ -237700,10 +237860,9 @@ var WikiTransformer = class {
237700
237860
  return false;
237701
237861
  if (uri.startsWith("wiki:"))
237702
237862
  return true;
237703
- if (uri.match(ANY_WIKIPEDIA_ORG))
237704
- return true;
237705
- if (withoutHttp(uri).startsWith(withoutHttp(this.wikiUrl)))
237706
- return true;
237863
+ if (uri.match(ANY_WIKIPEDIA_ORG) || withoutHttp(uri).startsWith(withoutHttp(this.wikiUrl))) {
237864
+ return !uri.match(/\/w\/index\.php(\?[^/]*)?$/);
237865
+ }
237707
237866
  return false;
237708
237867
  }
237709
237868
  pageName(uri) {
@@ -281732,11 +281891,44 @@ var bibliographyDirective = {
281732
281891
  };
281733
281892
 
281734
281893
  // ../myst-directives/dist/code.js
281735
- function parseEmphasizeLines(emphasizeLinesString) {
281894
+ function parseEmphasizeLines(data, vfile2, emphasizeLinesString) {
281895
+ const { node: node3 } = data;
281736
281896
  if (!emphasizeLinesString)
281737
281897
  return void 0;
281738
- const emphasizeLines = emphasizeLinesString === null || emphasizeLinesString === void 0 ? void 0 : emphasizeLinesString.split(",").map((val) => Number(val.trim())).filter((val) => Number.isInteger(val));
281739
- return emphasizeLines;
281898
+ const result = /* @__PURE__ */ new Set();
281899
+ for (const part of emphasizeLinesString.split(",")) {
281900
+ const trimmed = part.trim();
281901
+ const rangeMatch = trimmed.match(/^(\d+)\s*-\s*(\d+)$/);
281902
+ if (rangeMatch) {
281903
+ const start = Number(rangeMatch[1]);
281904
+ const end = Number(rangeMatch[2]);
281905
+ if (start <= end) {
281906
+ for (let i2 = start; i2 <= end; i2++) {
281907
+ result.add(i2);
281908
+ }
281909
+ continue;
281910
+ } else {
281911
+ fileWarn(vfile2, `Invalid emphasize-lines range "${trimmed}" (start > end)`, {
281912
+ node: node3,
281913
+ source: "code-block:options",
281914
+ ruleId: RuleId.directiveOptionsCorrect
281915
+ });
281916
+ continue;
281917
+ }
281918
+ }
281919
+ if (/^\d+$/.test(trimmed)) {
281920
+ result.add(Number(trimmed));
281921
+ } else if (trimmed !== "") {
281922
+ fileWarn(vfile2, `Invalid emphasize-lines value "${trimmed}"`, {
281923
+ node: node3,
281924
+ source: "code-block:options",
281925
+ ruleId: RuleId.directiveOptionsCorrect
281926
+ });
281927
+ }
281928
+ }
281929
+ if (result.size === 0)
281930
+ return void 0;
281931
+ return Array.from(result).sort((a2, b) => a2 - b);
281740
281932
  }
281741
281933
  function getCodeBlockOptions(data, vfile2, defaultFilename) {
281742
281934
  var _a6;
@@ -281748,7 +281940,7 @@ function getCodeBlockOptions(data, vfile2, defaultFilename) {
281748
281940
  ruleId: RuleId.directiveOptionsCorrect
281749
281941
  });
281750
281942
  }
281751
- const emphasizeLines = parseEmphasizeLines(options === null || options === void 0 ? void 0 : options["emphasize-lines"]);
281943
+ const emphasizeLines = parseEmphasizeLines(data, vfile2, options === null || options === void 0 ? void 0 : options["emphasize-lines"]);
281752
281944
  const numberLines = options === null || options === void 0 ? void 0 : options["number-lines"];
281753
281945
  const showLineNumbers = (options === null || options === void 0 ? void 0 : options.linenos) || (options === null || options === void 0 ? void 0 : options["lineno-start"]) || (options === null || options === void 0 ? void 0 : options["lineno-match"]) || numberLines ? true : void 0;
281754
281946
  let startingLineNumber = numberLines != null && numberLines > 1 ? numberLines : options === null || options === void 0 ? void 0 : options["lineno-start"];
@@ -281789,7 +281981,7 @@ var CODE_DIRECTIVE_OPTIONS = {
281789
281981
  },
281790
281982
  "emphasize-lines": {
281791
281983
  type: String,
281792
- doc: 'Emphasize particular lines (comma-separated numbers), e.g. "3,5"'
281984
+ doc: 'Emphasize particular lines (comma-separated numbers which can include ranges), e.g. "3,5,7-9"'
281793
281985
  },
281794
281986
  filename: {
281795
281987
  type: String,
@@ -289736,7 +289928,7 @@ var import_mime_types = __toESM(require_mime_types(), 1);
289736
289928
  var import_node_path16 = __toESM(require("path"), 1);
289737
289929
 
289738
289930
  // ../myst-cli/dist/version.js
289739
- var version2 = "1.3.27";
289931
+ var version2 = "1.4.0";
289740
289932
  var version_default2 = version2;
289741
289933
 
289742
289934
  // ../myst-cli/dist/utils/headers.js
@@ -291200,7 +291392,6 @@ function getLocation(file, projectPath) {
291200
291392
  }
291201
291393
  async function loadFile(session, file, projectPath, extension, opts) {
291202
291394
  var _a6;
291203
- await session.loadPlugins();
291204
291395
  const toc = tic();
291205
291396
  session.store.dispatch(warnings.actions.clearWarnings({ file }));
291206
291397
  const cache = castSession(session);
@@ -291660,6 +291851,7 @@ async function resolveProjectConfigPaths(session, path44, projectConfig, resolut
291660
291851
  return info;
291661
291852
  }
291662
291853
  }));
291854
+ await session.loadPlugins(resolvedFields.plugins);
291663
291855
  }
291664
291856
  if (projectConfig.parts) {
291665
291857
  resolvedFields.parts = await loadFrontmatterParts(session, file, "project.parts", { parts: projectConfig.parts }, path44);
@@ -298320,7 +298512,8 @@ function projectFromTOC(session, path44, toc, level = 1, file, opts) {
298320
298512
  }
298321
298513
  if ((opts === null || opts === void 0 ? void 0 : opts.urlFolders) && !opts.projectPath)
298322
298514
  opts.projectPath = path44;
298323
- const { slug } = fileInfo2(indexFile, pageSlugs, { ...opts, session });
298515
+ const slug = "index";
298516
+ pageSlugs[slug] = 1;
298324
298517
  const pages = [];
298325
298518
  pagesFromEntries(session, path44, entries2, pages, level, pageSlugs, opts);
298326
298519
  return { path: path44 || ".", file: indexFile, index: slug, pages };
@@ -300244,7 +300437,7 @@ var KIND_TO_EXT = {
300244
300437
  site: void 0
300245
300438
  };
300246
300439
  var DEFAULT_TEMPLATES = {
300247
- tex: "tex/myst/curvenote",
300440
+ tex: "tex/myst/plain_latex",
300248
300441
  typst: "typst/myst/lapreprint-typst",
300249
300442
  docx: "docx/myst/default",
300250
300443
  site: "site/myst/book-theme"
@@ -302012,8 +302205,8 @@ function makeNamedExportOption(description) {
302012
302205
  function makeStrictOption() {
302013
302206
  return new Option("--strict", "Summarize build warnings and stop on any errors.").default(false);
302014
302207
  }
302015
- function makeForceOption() {
302016
- return new Option("--force", "Build outputs for the given format, even if corresponding exports are not defined in file frontmatter").default(false);
302208
+ function makeForceOption(description) {
302209
+ return new Option("--force", description).default(false);
302017
302210
  }
302018
302211
  function makeCheckLinksOption() {
302019
302212
  return new Option("--check-links", "Check all links to websites resolve.").default(false);
@@ -321198,7 +321391,7 @@ async function clean2(session, files, opts) {
321198
321391
 
321199
321392
  // ../myst-cli/dist/cli/build.js
321200
321393
  function makeBuildCommand() {
321201
- const command = new Command("build").description("Build PDF, LaTeX, Word and website exports from MyST files").argument("[files...]", "list of files to export").addOption(makeExecuteOption("Execute Notebooks")).addOption(makePdfOption("Build PDF output")).addOption(makeTexOption("Build LaTeX outputs")).addOption(makeTypstOption("Build Typst outputs")).addOption(makeDocxOption("Build Docx output")).addOption(makeMdOption("Build MD output")).addOption(makeJatsOption("Build JATS xml output")).addOption(makeMecaOptions("Build MECA zip output")).addOption(makeCffOption("Build CFF output")).addOption(makeSiteOption(`Build ${readableName()} site content`)).addOption(makeHtmlOption("Build static HTML site content")).addOption(makeAllOption("Build all exports")).addOption(makeDOIBibOption()).addOption(makeWatchOption()).addOption(makeNamedExportOption("Output file for the export")).addOption(makeForceOption()).addOption(makeCheckLinksOption()).addOption(makeStrictOption()).addOption(makeCIOption()).addOption(makeMaxSizeWebpOption());
321394
+ const command = new Command("build").description("Build PDF, LaTeX, Word and website exports from MyST files").argument("[files...]", "list of files to export").addOption(makeExecuteOption("Execute Notebooks")).addOption(makePdfOption("Build PDF output")).addOption(makeTexOption("Build LaTeX outputs")).addOption(makeTypstOption("Build Typst outputs")).addOption(makeDocxOption("Build Docx output")).addOption(makeMdOption("Build MD output")).addOption(makeJatsOption("Build JATS xml output")).addOption(makeMecaOptions("Build MECA zip output")).addOption(makeCffOption("Build CFF output")).addOption(makeSiteOption(`Build ${readableName()} site content`)).addOption(makeHtmlOption("Build static HTML site content")).addOption(makeAllOption("Build all exports")).addOption(makeDOIBibOption()).addOption(makeWatchOption()).addOption(makeNamedExportOption("Output file for the export")).addOption(makeForceOption("Build outputs for the given format, even if corresponding exports are not defined in file frontmatter")).addOption(makeCheckLinksOption()).addOption(makeStrictOption()).addOption(makeCIOption()).addOption(makeMaxSizeWebpOption());
321202
321395
  return command;
321203
321396
  }
321204
321397
 
@@ -326381,36 +326574,28 @@ ${stderr}
326381
326574
  }
326382
326575
 
326383
326576
  // ../myst-cli/dist/plugins.js
326384
- async function loadPlugins(session) {
326385
- let configPlugins = [];
326386
- const state = session.store.getState();
326387
- const projConfig = selectors_exports.selectCurrentProjectConfig(state);
326388
- if (projConfig === null || projConfig === void 0 ? void 0 : projConfig.plugins)
326389
- configPlugins.push(...projConfig.plugins);
326390
- const siteConfig = selectors_exports.selectCurrentSiteConfig(state);
326391
- if (siteConfig === null || siteConfig === void 0 ? void 0 : siteConfig.projects) {
326392
- siteConfig.projects.filter((project) => !!project.path).forEach((project) => {
326393
- const siteProjConfig = selectors_exports.selectLocalProjectConfig(state, project.path);
326394
- if (siteProjConfig === null || siteProjConfig === void 0 ? void 0 : siteProjConfig.plugins)
326395
- configPlugins.push(...siteProjConfig.plugins);
326396
- });
326397
- }
326398
- configPlugins = [...new Map(configPlugins.map((info) => [info.path, info])).values()];
326399
- const plugins3 = {
326577
+ async function loadPlugins(session, plugins3) {
326578
+ var _a6;
326579
+ const loadedPlugins = (_a6 = session.plugins) !== null && _a6 !== void 0 ? _a6 : {
326400
326580
  directives: [],
326401
326581
  roles: [],
326402
- transforms: []
326582
+ transforms: [],
326583
+ paths: []
326403
326584
  };
326404
- if (configPlugins.length === 0) {
326405
- return plugins3;
326585
+ const newPlugins = [...new Map(plugins3.map((info) => [info.path, info])).values()].filter(
326586
+ // ...and filter out already loaded plugins
326587
+ ({ path: path44 }) => !loadedPlugins.paths.includes(path44)
326588
+ );
326589
+ if (newPlugins.length === 0) {
326590
+ return loadedPlugins;
326406
326591
  }
326407
- session.log.debug(`Loading plugins: "${configPlugins.map((info) => `${info.path} (${info.type})`).join('", "')}"`);
326408
- const modules = await Promise.all(configPlugins.map(async (info) => {
326409
- var _a6, _b;
326592
+ session.log.debug(`Loading plugins: "${newPlugins.map((info) => `${info.path} (${info.type})`).join('", "')}"`);
326593
+ const modules = await Promise.all(newPlugins.map(async (info) => {
326594
+ var _a7, _b;
326410
326595
  const { type: type2, path: path44 } = info;
326411
326596
  switch (type2) {
326412
326597
  case "executable": {
326413
- if (!((_a6 = import_node_fs44.default.statSync(path44, { throwIfNoEntry: false })) === null || _a6 === void 0 ? void 0 : _a6.isFile())) {
326598
+ if (!((_a7 = import_node_fs44.default.statSync(path44, { throwIfNoEntry: false })) === null || _a7 === void 0 ? void 0 : _a7.isFile())) {
326414
326599
  addWarningForFile(session, path44, `Unknown plugin "${path44}", it must be an executable file`, "error", {
326415
326600
  ruleId: RuleId.pluginLoads
326416
326601
  });
@@ -326460,26 +326645,28 @@ ${error === null || error === void 0 ? void 0 : error.stack}
326460
326645
  }
326461
326646
  }));
326462
326647
  modules.forEach((pluginLoader) => {
326463
- var _a6;
326648
+ var _a7;
326464
326649
  if (!pluginLoader)
326465
326650
  return;
326466
326651
  const plugin5 = pluginLoader.module.default || pluginLoader.module.plugin;
326467
326652
  const directives = plugin5.directives || pluginLoader.module.directives;
326468
326653
  const roles = plugin5.roles || pluginLoader.module.roles;
326469
326654
  const transforms = plugin5.transforms || pluginLoader.module.transforms;
326470
- session.log.info(`\u{1F50C} ${(_a6 = plugin5 === null || plugin5 === void 0 ? void 0 : plugin5.name) !== null && _a6 !== void 0 ? _a6 : "Unnamed Plugin"} (${pluginLoader.path}) loaded: ${plural("%s directive(s)", directives)}, ${plural("%s role(s)", roles)}, ${plural("%s transform(s)", transforms)}`);
326655
+ session.log.info(`\u{1F50C} ${(_a7 = plugin5 === null || plugin5 === void 0 ? void 0 : plugin5.name) !== null && _a7 !== void 0 ? _a7 : "Unnamed Plugin"} (${pluginLoader.path}) loaded: ${plural("%s directive(s)", directives)}, ${plural("%s role(s)", roles)}, ${plural("%s transform(s)", transforms)}`);
326471
326656
  if (directives) {
326472
- plugins3.directives.push(...directives);
326657
+ loadedPlugins.directives.push(...directives);
326473
326658
  }
326474
326659
  if (roles) {
326475
- plugins3.roles.push(...roles);
326660
+ loadedPlugins.roles.push(...roles);
326476
326661
  }
326477
326662
  if (transforms) {
326478
- plugins3.transforms.push(...transforms);
326663
+ loadedPlugins.transforms.push(...transforms);
326479
326664
  }
326665
+ loadedPlugins.paths.push(pluginLoader.path);
326480
326666
  });
326667
+ session.plugins = loadedPlugins;
326481
326668
  session.log.debug("Plugins loaded");
326482
- return plugins3;
326669
+ return loadedPlugins;
326483
326670
  }
326484
326671
 
326485
326672
  // ../myst-cli/dist/session/session.js
@@ -333145,11 +333332,8 @@ var Session = class {
333145
333332
  logData.done = true;
333146
333333
  return resp;
333147
333334
  }
333148
- async loadPlugins() {
333149
- if (this._pluginPromise)
333150
- return this._pluginPromise;
333151
- this._pluginPromise = loadPlugins(this);
333152
- this.plugins = await this._pluginPromise;
333335
+ async loadPlugins(plugins3) {
333336
+ this.plugins = await loadPlugins(this, plugins3);
333153
333337
  return this.plugins;
333154
333338
  }
333155
333339
  sourcePath() {
@@ -333845,7 +334029,7 @@ function getKind(session, kinds) {
333845
334029
  return void 0;
333846
334030
  const { pdf, tex, typst, docx, site } = kinds;
333847
334031
  if (pdf)
333848
- session.log.warn('PDF templates may use either "tex" or "typst"');
334032
+ session.log.warn('PDF templates may be either "tex" or "typst", including both.');
333849
334033
  const flags = {
333850
334034
  [TemplateKind.tex]: (tex || pdf) ?? false,
333851
334035
  [TemplateKind.typst]: (typst || pdf) ?? false,
@@ -333860,8 +334044,11 @@ function getKind(session, kinds) {
333860
334044
  async function downloadTemplateCLI(session, template, path44, opts) {
333861
334045
  const templateKind = getKindFromName(template);
333862
334046
  const kinds = templateKind ? [templateKind] : getKind(session, opts);
333863
- if (!kinds || kinds.length > 1) {
333864
- throw new Error("Cannot lookup a template with more than one kind.");
334047
+ if (!(kinds == null ? void 0 : kinds.length)) {
334048
+ throw new Error("Cannot lookup a template without specifying a kind (e.g. typst).");
334049
+ }
334050
+ if (kinds.length > 1) {
334051
+ throw new Error("Cannot lookup a template when more than one kind is specified.");
333865
334052
  }
333866
334053
  const kind = kinds[0];
333867
334054
  const { templatePath: defaultTemplatePath, templateUrl } = resolveInputs(session, {
@@ -333968,7 +334155,7 @@ Tags: ${source_default8.dim(
333968
334155
  });
333969
334156
  }
333970
334157
  function makeDownloadCLI(program3) {
333971
- const command = new Command("download").description("Download a public template to a path").argument("<template>", "The template URL or name").argument("[path]", "A folder to download and unzip the template to").addOption(makePdfOption("Download PDF template")).addOption(makeTexOption("Download LaTeX template")).addOption(makeTypstOption("Download Typst template")).addOption(makeDocxOption("Download Docx template")).addOption(makeSiteOption("Download Site template")).addOption(makeForceOption()).action(clirun2(Session, downloadTemplateCLI, program3));
334158
+ const command = new Command("download").description("Download a public template to a path").argument("<template>", "The template URL or name").argument("[path]", "A folder to download and unzip the template to").addOption(makePdfOption("Download PDF template")).addOption(makeTexOption("Download LaTeX template")).addOption(makeTypstOption("Download Typst template")).addOption(makeDocxOption("Download Docx template")).addOption(makeSiteOption("Download Site template")).addOption(makeForceOption("Overwrite existing downloaded templates")).action(clirun2(Session, downloadTemplateCLI, program3));
333972
334159
  return command;
333973
334160
  }
333974
334161
  function makeListCLI(program3) {
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes