mirror of
https://github.com/vesan/obsidian-table-beautifier.git
synced 2026-07-22 06:53:19 +00:00
Merge pull request #6 from vesan/test/improve-coverage
test: expand coverage and report it in CI
This commit is contained in:
commit
0962161cb8
11 changed files with 448 additions and 9 deletions
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
|
|
@ -16,4 +16,14 @@ jobs:
|
|||
cache: npm
|
||||
- run: npm ci
|
||||
- run: npm run build
|
||||
- run: npm test
|
||||
- run: npm run test:coverage
|
||||
|
||||
- name: Coverage summary
|
||||
if: always()
|
||||
run: |
|
||||
if [ -f coverage/coverage-summary.json ]; then
|
||||
LINE=$(jq -r '.total.lines.pct' coverage/coverage-summary.json)
|
||||
echo "## Code Coverage" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Line coverage: ${LINE}%**" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -2,3 +2,4 @@ node_modules
|
|||
main.js
|
||||
*.js.map
|
||||
data.json
|
||||
coverage
|
||||
|
|
|
|||
244
package-lock.json
generated
244
package-lock.json
generated
|
|
@ -9,12 +9,73 @@
|
|||
"version": "1.0.1",
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"@vitest/coverage-v8": "^4.1.7",
|
||||
"esbuild": "^0.28.0",
|
||||
"obsidian": "*",
|
||||
"obsidian": "latest",
|
||||
"typescript": "^5.3.0",
|
||||
"vitest": "^4.1.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-string-parser": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
|
||||
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-validator-identifier": {
|
||||
"version": "7.28.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
|
||||
"integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.29.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz",
|
||||
"integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.29.0"
|
||||
},
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
|
||||
"integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-string-parser": "^7.27.1",
|
||||
"@babel/helper-validator-identifier": "^7.28.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@bcoe/v8-coverage": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz",
|
||||
"integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/state": {
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.0.tgz",
|
||||
|
|
@ -516,6 +577,16 @@
|
|||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/resolve-uri": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/sourcemap-codec": {
|
||||
"version": "1.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
|
||||
|
|
@ -523,6 +594,17 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@jridgewell/trace-mapping": {
|
||||
"version": "0.3.31",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
|
||||
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/resolve-uri": "^3.1.0",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@marijn/find-cluster-break": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz",
|
||||
|
|
@ -897,6 +979,37 @@
|
|||
"@types/estree": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/coverage-v8": {
|
||||
"version": "4.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.7.tgz",
|
||||
"integrity": "sha512-qsYPeXc5Q9dFLd1i8Ap+Bx8sQgcp+rFVQo4R0dDsWNBzl26ldVF1qOO+RL24K7FDrR6pA+50XedRLSoSG24bVQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@bcoe/v8-coverage": "^1.0.2",
|
||||
"@vitest/utils": "4.1.7",
|
||||
"ast-v8-to-istanbul": "^1.0.0",
|
||||
"istanbul-lib-coverage": "^3.2.2",
|
||||
"istanbul-lib-report": "^3.0.1",
|
||||
"istanbul-reports": "^3.2.0",
|
||||
"magicast": "^0.5.2",
|
||||
"obug": "^2.1.1",
|
||||
"std-env": "^4.0.0-rc.1",
|
||||
"tinyrainbow": "^3.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/vitest"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vitest/browser": "4.1.7",
|
||||
"vitest": "4.1.7"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@vitest/browser": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/expect": {
|
||||
"version": "4.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.7.tgz",
|
||||
|
|
@ -1020,6 +1133,18 @@
|
|||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/ast-v8-to-istanbul": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.0.tgz",
|
||||
"integrity": "sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/trace-mapping": "^0.3.31",
|
||||
"estree-walker": "^3.0.3",
|
||||
"js-tokens": "^10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/chai": {
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz",
|
||||
|
|
@ -1157,6 +1282,69 @@
|
|||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/html-escaper": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
|
||||
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/istanbul-lib-coverage": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
|
||||
"integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/istanbul-lib-report": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
|
||||
"integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"istanbul-lib-coverage": "^3.0.0",
|
||||
"make-dir": "^4.0.0",
|
||||
"supports-color": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/istanbul-reports": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz",
|
||||
"integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"html-escaper": "^2.0.0",
|
||||
"istanbul-lib-report": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz",
|
||||
"integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lightningcss": {
|
||||
"version": "1.32.0",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
|
||||
|
|
@ -1428,6 +1616,34 @@
|
|||
"@jridgewell/sourcemap-codec": "^1.5.5"
|
||||
}
|
||||
},
|
||||
"node_modules/magicast": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.3.tgz",
|
||||
"integrity": "sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.29.3",
|
||||
"@babel/types": "^7.29.0",
|
||||
"source-map-js": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/make-dir": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
|
||||
"integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"semver": "^7.5.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/moment": {
|
||||
"version": "2.29.4",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
|
||||
|
|
@ -1573,6 +1789,19 @@
|
|||
"@rolldown/binding-win32-x64-msvc": "1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz",
|
||||
"integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/siginfo": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
|
||||
|
|
@ -1612,6 +1841,19 @@
|
|||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/tinybench": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
|
||||
|
|
|
|||
|
|
@ -7,10 +7,12 @@
|
|||
"dev": "node esbuild.config.mjs",
|
||||
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest"
|
||||
"test:watch": "vitest",
|
||||
"test:coverage": "vitest run --coverage"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"@vitest/coverage-v8": "^4.1.7",
|
||||
"esbuild": "^0.28.0",
|
||||
"obsidian": "latest",
|
||||
"typescript": "^5.3.0",
|
||||
|
|
|
|||
|
|
@ -82,4 +82,49 @@ describe("convertSelection", () => {
|
|||
|
||||
expect(editor.getValue()).toBe(doc);
|
||||
});
|
||||
|
||||
it("does nothing when the selection is empty", () => {
|
||||
const doc = "│ A │ B │\n│ 1 │ 2 │";
|
||||
const editor = new FakeEditor(doc, { line: 0, ch: 5 }, { line: 0, ch: 5 });
|
||||
|
||||
convertSelection(editor as unknown as Editor);
|
||||
|
||||
expect(editor.getValue()).toBe(doc);
|
||||
});
|
||||
|
||||
it("trims the trailing line when the selection ends at column 0 of the next line", () => {
|
||||
// Mimics a triple-click drag: selection extends through "\n" onto a new line.
|
||||
const doc =
|
||||
"┌──────┬──────┐\n" +
|
||||
"│ A │ B │\n" +
|
||||
"├──────┼──────┤\n" +
|
||||
"│ 1 │ 2 │\n" +
|
||||
"└──────┴──────┘\n" +
|
||||
"after";
|
||||
const editor = new FakeEditor(doc, { line: 0, ch: 0 }, { line: 5, ch: 0 });
|
||||
|
||||
convertSelection(editor as unknown as Editor);
|
||||
|
||||
expect(editor.getValue()).toBe(
|
||||
"| A | B |\n" + "| - | - |\n" + "| 1 | 2 |\n" + "after"
|
||||
);
|
||||
});
|
||||
|
||||
it("preserves text before and after a table embedded mid-document", () => {
|
||||
const doc =
|
||||
"before\n" +
|
||||
"┌──────┬──────┐\n" +
|
||||
"│ A │ B │\n" +
|
||||
"├──────┼──────┤\n" +
|
||||
"│ 1 │ 2 │\n" +
|
||||
"└──────┴──────┘\n" +
|
||||
"after";
|
||||
const editor = new FakeEditor(doc, { line: 1, ch: 0 }, { line: 5, ch: 15 });
|
||||
|
||||
convertSelection(editor as unknown as Editor);
|
||||
|
||||
expect(editor.getValue()).toBe(
|
||||
"before\n" + "| A | B |\n" + "| - | - |\n" + "| 1 | 2 |\n" + "after"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
26
src/__tests__/detect.test.ts
Normal file
26
src/__tests__/detect.test.ts
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import { describe, it, expect } from "vitest";
|
||||
import { looksLikeTable } from "../detect";
|
||||
|
||||
describe("looksLikeTable", () => {
|
||||
it("detects Unicode box-drawing characters", () => {
|
||||
expect(looksLikeTable("│ a │ b │")).toBe(true);
|
||||
expect(looksLikeTable("┌──┬──┐")).toBe(true);
|
||||
expect(looksLikeTable("└──┴──┘")).toBe(true);
|
||||
expect(looksLikeTable("├──┼──┤")).toBe(true);
|
||||
});
|
||||
|
||||
it("detects ASCII borders with dashes and equals", () => {
|
||||
expect(looksLikeTable("+----+----+")).toBe(true);
|
||||
expect(looksLikeTable("+====+====+")).toBe(true);
|
||||
});
|
||||
|
||||
it("rejects plain prose", () => {
|
||||
expect(looksLikeTable("Just some regular text.")).toBe(false);
|
||||
expect(looksLikeTable("Two\nlines, no table.")).toBe(false);
|
||||
});
|
||||
|
||||
it("rejects a plain Markdown table without box-drawing or +-+ borders", () => {
|
||||
const md = "| a | b |\n| - | - |\n| 1 | 2 |";
|
||||
expect(looksLikeTable(md)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
|
@ -30,6 +30,11 @@ describe("looksLikeIdentifier", () => {
|
|||
expect(looksLikeIdentifier("admin")).toBe(false);
|
||||
expect(looksLikeIdentifier("hello")).toBe(false);
|
||||
});
|
||||
|
||||
it("detects colon-separated identifiers", () => {
|
||||
expect(looksLikeIdentifier("Foo:Bar")).toBe(true);
|
||||
expect(looksLikeIdentifier("namespace:type")).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("formatMarkdownTable", () => {
|
||||
|
|
@ -99,6 +104,30 @@ describe("formatMarkdownTable", () => {
|
|||
expect(result).toContain("fixed via ShowableScope");
|
||||
});
|
||||
|
||||
it("does not wrap header values in backticks even when they look like identifiers", () => {
|
||||
const table: ParsedTable = {
|
||||
headers: ["MyClass", "Note"],
|
||||
rows: [["plain", "text"]],
|
||||
};
|
||||
|
||||
const result = formatMarkdownTable(table);
|
||||
const headerLine = result.split("\n")[0];
|
||||
|
||||
expect(headerLine).toContain("MyClass");
|
||||
expect(headerLine).not.toContain("`MyClass`");
|
||||
});
|
||||
|
||||
it("formats a single-row table", () => {
|
||||
const table: ParsedTable = {
|
||||
headers: ["A", "B"],
|
||||
rows: [["1", "2"]],
|
||||
};
|
||||
|
||||
expect(formatMarkdownTable(table)).toBe(
|
||||
"| A | B |\n| - | - |\n| 1 | 2 |"
|
||||
);
|
||||
});
|
||||
|
||||
it("handles empty cells", () => {
|
||||
const table: ParsedTable = {
|
||||
headers: ["A", "B"],
|
||||
|
|
|
|||
|
|
@ -131,6 +131,75 @@ describe("parseTable", () => {
|
|||
]);
|
||||
});
|
||||
|
||||
it("parses an ASCII table with = borders", () => {
|
||||
const input = `+======+======+
|
||||
| Name | Age |
|
||||
+======+======+
|
||||
| Eve | 22 |
|
||||
+======+======+`;
|
||||
|
||||
const result = parseTable(input);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result!.headers).toEqual(["Name", "Age"]);
|
||||
expect(result!.rows).toEqual([["Eve", "22"]]);
|
||||
});
|
||||
|
||||
it("parses an existing Markdown pipe table", () => {
|
||||
const input = `| Name | Age |
|
||||
| ---- | --- |
|
||||
| Dana | 31 |
|
||||
| Erik | 28 |`;
|
||||
|
||||
const result = parseTable(input);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result!.headers).toEqual(["Name", "Age"]);
|
||||
expect(result!.rows).toEqual([
|
||||
["Dana", "31"],
|
||||
["Erik", "28"],
|
||||
]);
|
||||
});
|
||||
|
||||
it("drops rows whose column count differs from the header", () => {
|
||||
const input = `│ A │ B │
|
||||
│ 1 │ 2 │
|
||||
│ x │ y │ z │
|
||||
│ 3 │ 4 │`;
|
||||
|
||||
const result = parseTable(input);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result!.headers).toEqual(["A", "B"]);
|
||||
expect(result!.rows).toEqual([
|
||||
["1", "2"],
|
||||
["3", "4"],
|
||||
]);
|
||||
});
|
||||
|
||||
it("handles mixed │ and | delimiters across lines", () => {
|
||||
const input = `│ A │ B │
|
||||
| 1 | 2 |`;
|
||||
|
||||
const result = parseTable(input);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result!.headers).toEqual(["A", "B"]);
|
||||
expect(result!.rows).toEqual([["1", "2"]]);
|
||||
});
|
||||
|
||||
it("tolerates blank lines between data rows when no border is present", () => {
|
||||
const input = `│ A │ B │
|
||||
|
||||
│ 1 │ 2 │`;
|
||||
|
||||
const result = parseTable(input);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result!.headers).toEqual(["A", "B"]);
|
||||
expect(result!.rows).toEqual([["1", "2"]]);
|
||||
});
|
||||
|
||||
it("handles a three-column table", () => {
|
||||
const input = `┌──────┬──────┬──────┐
|
||||
│ A │ B │ C │
|
||||
|
|
|
|||
8
src/detect.ts
Normal file
8
src/detect.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
const TABLE_HINT = /[│┌┬┐├┼┤└┴┘─]/;
|
||||
|
||||
// Quick heuristic gate used by main.ts before the more expensive parseTable.
|
||||
// True for ASCII box-drawing tables and +---+ / +===+ ruled tables; false for
|
||||
// plain prose and plain Markdown pipe tables (which need no conversion).
|
||||
export function looksLikeTable(text: string): boolean {
|
||||
return TABLE_HINT.test(text) || /\+[-=]+\+/.test(text);
|
||||
}
|
||||
|
|
@ -1,11 +1,6 @@
|
|||
import { Editor, Menu, Plugin } from "obsidian";
|
||||
import { convertSelection } from "./convert";
|
||||
|
||||
const TABLE_HINT = /[│┌┬┐├┼┤└┴┘─]/;
|
||||
|
||||
function looksLikeTable(text: string): boolean {
|
||||
return TABLE_HINT.test(text) || /\+[-=]+\+/.test(text);
|
||||
}
|
||||
import { looksLikeTable } from "./detect";
|
||||
|
||||
export default class TableBeautifierPlugin extends Plugin {
|
||||
onload() {
|
||||
|
|
|
|||
12
vitest.config.ts
Normal file
12
vitest.config.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { defineConfig } from "vitest/config";
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
coverage: {
|
||||
provider: "v8",
|
||||
include: ["src/**/*.ts"],
|
||||
exclude: ["src/**/__tests__/**"],
|
||||
reporter: ["text", "html", "json-summary"],
|
||||
},
|
||||
},
|
||||
});
|
||||
Loading…
Reference in a new issue