@doccident/doccident 0.0.2 → 0.0.4

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,35 +1,58 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- var isStartOfSnippet = function (line) {
4
- return line.trim().match(/```\W*(JavaScript|js|es6)\s?$/i);
5
- };
6
- var isEndOfSnippet = function (line) { return line.trim() === "```"; };
7
- var isSkip = function (line) { return line.trim() === "<!-- skip-example -->"; };
8
- var isCodeSharedInFile = function (line) {
9
- return line.trim() === "<!-- share-code-between-examples -->";
10
- };
11
- function startNewSnippet(snippets, fileName, lineNumber) {
12
- var skip = snippets.skip;
3
+ // Capture indentation (group 1) and language (group 2)
4
+ const START_REGEX = /^(\s*)```\W*(JavaScript|js|es6|ts|typescript|python|py|bash|sh|zsh|shell|go|rust|rs|fortran|f90|f95|cobol|cob|c)\s?$/i;
5
+ const isStartOfSnippet = (line) => line.match(START_REGEX);
6
+ const isEndOfSnippet = (line) => line.trim() === "```";
7
+ const isSkip = (line) => line.trim() === "<!-- skip-example -->";
8
+ const isCodeSharedInFile = (line) => line.trim() === "<!-- share-code-between-examples -->";
9
+ function startNewSnippet(snippets, fileName, lineNumber, language, indentation) {
10
+ const skip = snippets.skip;
13
11
  snippets.skip = false;
12
+ let normalizedLang = 'javascript';
13
+ const langLower = language.toLowerCase();
14
+ if (['python', 'py'].includes(langLower)) {
15
+ normalizedLang = 'python';
16
+ }
17
+ else if (['bash', 'sh', 'zsh', 'shell'].includes(langLower)) {
18
+ normalizedLang = langLower === 'shell' ? 'bash' : langLower;
19
+ }
20
+ else if (langLower === 'go') {
21
+ normalizedLang = 'go';
22
+ }
23
+ else if (['rust', 'rs'].includes(langLower)) {
24
+ normalizedLang = 'rust';
25
+ }
26
+ else if (['fortran', 'f90', 'f95'].includes(langLower)) {
27
+ normalizedLang = 'fortran';
28
+ }
29
+ else if (['cobol', 'cob'].includes(langLower)) {
30
+ normalizedLang = 'cobol';
31
+ }
32
+ else if (langLower === 'c') {
33
+ normalizedLang = 'c';
34
+ }
14
35
  return Object.assign(snippets, {
15
36
  snippets: snippets.snippets.concat([
16
- { code: "", fileName: fileName, lineNumber: lineNumber, complete: false, skip: skip }
37
+ { code: "", language: normalizedLang, fileName, lineNumber, complete: false, skip: skip ?? false, indentation }
17
38
  ])
18
39
  });
19
40
  }
20
41
  function addLineToLastSnippet(line) {
21
42
  return function addLine(snippets) {
22
- var lastSnippet = snippets.snippets[snippets.snippets.length - 1];
43
+ const lastSnippet = snippets.snippets[snippets.snippets.length - 1];
23
44
  if (lastSnippet && !lastSnippet.complete) {
24
- lastSnippet.code += line + "\n";
45
+ let lineToAdd = line;
46
+ if (lastSnippet.indentation && line.startsWith(lastSnippet.indentation)) {
47
+ lineToAdd = line.slice(lastSnippet.indentation.length);
48
+ }
49
+ lastSnippet.code += lineToAdd + "\n";
25
50
  }
26
51
  return snippets;
27
52
  };
28
53
  }
29
- function endSnippet(snippets, fileName, lineNumber) {
30
- // eslint-disable-next-line no-console
31
- console.log("endSnippet", snippets, fileName, lineNumber);
32
- var lastSnippet = snippets.snippets[snippets.snippets.length - 1];
54
+ function endSnippet(snippets, _fileName, _lineNumber) {
55
+ const lastSnippet = snippets.snippets[snippets.snippets.length - 1];
33
56
  if (lastSnippet) {
34
57
  lastSnippet.complete = true;
35
58
  }
@@ -44,8 +67,10 @@ function shareCodeInFile(snippets) {
44
67
  return snippets;
45
68
  }
46
69
  function parseLine(line) {
47
- if (isStartOfSnippet(line)) {
48
- return startNewSnippet;
70
+ const startMatch = isStartOfSnippet(line);
71
+ if (startMatch) {
72
+ // startMatch[1] is indentation, startMatch[2] is language
73
+ return (snippets, fileName, lineNumber) => startNewSnippet(snippets, fileName, lineNumber, startMatch[2], startMatch[1]);
49
74
  }
50
75
  if (isEndOfSnippet(line)) {
51
76
  return endSnippet;
@@ -59,27 +84,25 @@ function parseLine(line) {
59
84
  return addLineToLastSnippet(line);
60
85
  }
61
86
  function parseCodeSnippets(args) {
62
- var contents = args.contents;
63
- var fileName = args.fileName;
64
- var initialState = {
87
+ const contents = args.contents;
88
+ const fileName = args.fileName;
89
+ const initialState = {
65
90
  snippets: [],
66
91
  shareCodeInFile: false,
67
92
  complete: false
68
93
  };
69
- var results = contents
94
+ const results = contents
70
95
  .split("\n")
71
96
  .map(parseLine)
72
- .reduce(function (snippets, lineAction, index) {
73
- return lineAction(snippets, fileName, index + 1);
74
- }, initialState);
75
- var codeSnippets = results.snippets;
76
- var lastSnippet = codeSnippets[codeSnippets.length - 1];
97
+ .reduce((snippets, lineAction, index) => lineAction(snippets, fileName, index + 1), initialState);
98
+ const codeSnippets = results.snippets;
99
+ const lastSnippet = codeSnippets[codeSnippets.length - 1];
77
100
  if (lastSnippet && !lastSnippet.complete) {
78
101
  throw new Error("Snippet parsing was incomplete");
79
102
  }
80
103
  return {
81
- fileName: fileName,
82
- codeSnippets: codeSnippets,
104
+ fileName,
105
+ codeSnippets,
83
106
  shareCodeInFile: results.shareCodeInFile
84
107
  };
85
108
  }
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.printResults = printResults;
7
+ /* eslint-disable no-console */
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ function printResults(results) {
10
+ results.filter((result) => result.status === "fail").forEach(printFailure);
11
+ const passingCount = results.filter((result) => result.status === "pass")
12
+ .length;
13
+ const failingCount = results.filter((result) => result.status === "fail")
14
+ .length;
15
+ const skippingCount = results.filter((result) => result.status === "skip")
16
+ .length;
17
+ function successfulRun() {
18
+ return failingCount === 0;
19
+ }
20
+ console.log(chalk_1.default.green("Passed: " + passingCount));
21
+ if (skippingCount > 0) {
22
+ console.log(chalk_1.default.yellow("Skipped: " + skippingCount));
23
+ }
24
+ if (successfulRun()) {
25
+ console.log(chalk_1.default.green("\nSuccess!"));
26
+ }
27
+ else {
28
+ console.log(chalk_1.default.red("Failed: " + failingCount));
29
+ }
30
+ }
31
+ function printFailure(result) {
32
+ console.log(chalk_1.default.red(`Failed - ${markDownErrorLocation(result)}`));
33
+ const stackDetails = relevantStackDetails(result.stack);
34
+ console.log(stackDetails);
35
+ const variableNotDefined = stackDetails.match(/(\w{1,256}) is not defined/);
36
+ if (variableNotDefined) {
37
+ const variableName = variableNotDefined[1];
38
+ console.log(`You can declare ${chalk_1.default.blue(variableName)} in the ${chalk_1.default.blue("globals")} section in ${chalk_1.default.grey(".doccident-setup.js")}`);
39
+ console.log(`
40
+ For example:
41
+ ${chalk_1.default.grey("// .doccident-setup.js")}
42
+ module.exports = {
43
+ globals: {
44
+ ${chalk_1.default.blue(variableName)}: ...
45
+ }
46
+ }
47
+ `);
48
+ }
49
+ }
50
+ function relevantStackDetails(stack) {
51
+ const evalIndex = stack.indexOf("at eval");
52
+ if (evalIndex !== -1) {
53
+ return stack.substring(0, evalIndex);
54
+ }
55
+ const lines = stack.split("\n");
56
+ for (let i = 0; i < lines.length; i++) {
57
+ const line = lines[i];
58
+ if (line.includes("doctest.js") && line.trim().startsWith("at ")) {
59
+ return lines.slice(0, i).join("\n") + "\n";
60
+ }
61
+ }
62
+ return stack;
63
+ }
64
+ function markDownErrorLocation(result) {
65
+ const lines = result.stack.split("\n");
66
+ for (const line of lines) {
67
+ if (line.includes("eval")) {
68
+ const match = line.match(/<([^><]+)>:(\d+):(\d+)/);
69
+ if (match) {
70
+ const mdLineNumber = parseInt(match[2], 10);
71
+ const columnNumber = parseInt(match[3], 10);
72
+ const lineNumber = result.codeSnippet.lineNumber + mdLineNumber;
73
+ return `${result.codeSnippet.fileName}:${lineNumber}:${columnNumber}`;
74
+ }
75
+ }
76
+ }
77
+ return `${result.codeSnippet.fileName}:${result.codeSnippet.lineNumber}`;
78
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/dist/utils.js ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.flatten = flatten;
4
+ function flatten(arr) {
5
+ return Array.prototype.concat.apply([], arr);
6
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doccident/doccident",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Test all the code in your markdown docs!",
5
5
  "main": "dist/doctest.js",
6
6
  "files": [
@@ -12,9 +12,10 @@
12
12
  },
13
13
  "scripts": {
14
14
  "build": "tsc",
15
- "lint": "eslint . --ext .ts",
16
- "test": "jest",
17
- "precommit": "npm run lint && npm run test",
15
+ "lint": "eslint .",
16
+ "test": "vitest run",
17
+ "test:readme": "node bin/cmd.js README.md",
18
+ "precommit": "npm run lint && npm run test && npm run test:readme",
18
19
  "clean": "rm -rf dist",
19
20
  "prepublishOnly": "npm run clean && npm run build"
20
21
  },
@@ -37,29 +38,22 @@
37
38
  },
38
39
  "homepage": "https://github.com/BillaudCipher/doccident",
39
40
  "devDependencies": {
40
- "@babel/preset-typescript": "^7.27.1",
41
41
  "@eslint/eslintrc": "^3.3.1",
42
42
  "@eslint/js": "^9.23.0",
43
43
  "@types/node": "^22.15.17",
44
44
  "@typescript-eslint/eslint-plugin": "^8.32.0",
45
45
  "@typescript-eslint/parser": "^8.32.0",
46
+ "@vitest/coverage-v8": "^4.0.16",
46
47
  "eslint": "^9.24.0",
47
48
  "eslint-plugin-import": "^2.31.0",
48
- "jest": "^29.7.0",
49
- "typescript": "^5.8.3"
49
+ "typescript": "^5.8.3",
50
+ "vitest": "^4.0.16"
50
51
  },
51
52
  "dependencies": {
52
- "@babel/core": "^7.27.1",
53
- "@babel/preset-env": "^7.27.2",
54
- "chalk": "^2.4.2",
55
- "commander": "^4.1.1",
56
- "glob": "^7.2.3",
53
+ "chalk": "^4.1.2",
54
+ "commander": "^14.0.2",
55
+ "esbuild": "^0.27.2",
56
+ "fast-glob": "^3.3.3",
57
57
  "globals": "^16.1.0"
58
- },
59
- "babel": {
60
- "presets": [
61
- "@babel/preset-env",
62
- "@babel/preset-typescript"
63
- ]
64
58
  }
65
59
  }