@contractkit/plugin-python 0.9.1

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.
Files changed (39) hide show
  1. package/.turbo/turbo-build$colon$ci.log +35 -0
  2. package/.turbo/turbo-build.log +15 -0
  3. package/.turbo/turbo-test$colon$ci.log +59 -0
  4. package/.turbo/turbo-test.log +15 -0
  5. package/CHANGELOG.md +118 -0
  6. package/README.md +86 -0
  7. package/coverage/base.css +224 -0
  8. package/coverage/block-navigation.js +87 -0
  9. package/coverage/clover.xml +559 -0
  10. package/coverage/coverage-final.json +4 -0
  11. package/coverage/favicon.png +0 -0
  12. package/coverage/index.html +131 -0
  13. package/coverage/prettify.css +1 -0
  14. package/coverage/prettify.js +2 -0
  15. package/coverage/sort-arrow-sprite.png +0 -0
  16. package/coverage/sorter.js +210 -0
  17. package/coverage/src/codegen-client.ts.html +2071 -0
  18. package/coverage/src/codegen-models.ts.html +1360 -0
  19. package/coverage/src/index.html +131 -0
  20. package/coverage/tests/helpers.ts.html +667 -0
  21. package/coverage/tests/index.html +116 -0
  22. package/dist/codegen-client.d.ts +30 -0
  23. package/dist/codegen-client.d.ts.map +1 -0
  24. package/dist/codegen-models.d.ts +19 -0
  25. package/dist/codegen-models.d.ts.map +1 -0
  26. package/dist/index.d.ts +17 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +1046 -0
  29. package/dist/index.js.map +1 -0
  30. package/eslint.config.js +6 -0
  31. package/package.json +45 -0
  32. package/src/codegen-client.ts +662 -0
  33. package/src/codegen-models.ts +425 -0
  34. package/src/index.ts +143 -0
  35. package/tests/codegen-client.test.ts +361 -0
  36. package/tests/codegen-models.test.ts +295 -0
  37. package/tests/helpers.ts +194 -0
  38. package/tsconfig.json +9 -0
  39. package/vitest.config.ts +14 -0
@@ -0,0 +1,35 @@
1
+
2
+ 
3
+ > @contractkit/plugin-python@0.9.0 build:ci /Users/robert/projects/contractkit/packages/plugin-python
4
+ > eslint --max-warnings=0 && pnpm run build
5
+
6
+ =============
7
+
8
+
9
+ WARNING: You are currently running a version of TypeScript which is not officially supported by @typescript-eslint/typescript-estree.
10
+
11
+
12
+ * @typescript-eslint/typescript-estree version: 8.57.2
13
+ * Supported TypeScript versions: >=4.8.4 <6.0.0
14
+ * Your TypeScript version: 6.0.2
15
+
16
+
17
+ Please only submit bug reports when using the officially supported version.
18
+
19
+
20
+ =============
21
+
22
+ > @contractkit/plugin-python@0.9.0 build /Users/robert/projects/contractkit/packages/plugin-python
23
+ > tsup src/index.ts --format esm --sourcemap --dts && tsc --emitDeclarationOnly --declaration
24
+
25
+ CLI Building entry: src/index.ts
26
+ CLI Using tsconfig: tsconfig.json
27
+ CLI tsup v8.5.1
28
+ CLI Target: esnext
29
+ ESM Build start
30
+ ESM dist/index.js 36.84 KB
31
+ ESM dist/index.js.map 76.54 KB
32
+ ESM ⚡️ Build success in 46ms
33
+ DTS Build start
34
+ DTS ⚡️ Build success in 602ms
35
+ DTS dist/index.d.ts 801.00 B
@@ -0,0 +1,15 @@
1
+
2
+ > @contractkit/plugin-python@0.9.0 build /Users/robert/projects/contractkit/packages/plugin-python
3
+ > tsup src/index.ts --format esm --sourcemap --dts && tsc --emitDeclarationOnly --declaration
4
+
5
+ CLI Building entry: src/index.ts
6
+ CLI Using tsconfig: tsconfig.json
7
+ CLI tsup v8.5.1
8
+ CLI Target: esnext
9
+ ESM Build start
10
+ ESM dist/index.js 36.84 KB
11
+ ESM dist/index.js.map 76.54 KB
12
+ ESM ⚡️ Build success in 97ms
13
+ DTS Build start
14
+ DTS ⚡️ Build success in 631ms
15
+ DTS dist/index.d.ts 801.00 B
@@ -0,0 +1,59 @@
1
+
2
+ 
3
+ > @contractkit/plugin-python@0.9.0 test:ci /Users/robert/projects/contractkit/packages/plugin-python
4
+ > vitest run --coverage
5
+
6
+ [?25l
7
+  RUN  v4.1.5 /Users/robert/projects/contractkit/packages/plugin-python
8
+ Coverage enabled with v8
9
+
10
+ [?2026h
11
+  ❯ tests/codegen-models.test.ts [queued]
12
+
13
+  Test Files 0 passed (2)
14
+  Tests 0 passed (0)
15
+  Start at 08:51:08
16
+  Duration 308ms
17
+ [?2026l[?2026h
18
+  ❯ tests/codegen-client.test.ts [queued]
19
+  ❯ tests/codegen-models.test.ts [queued]
20
+
21
+  Test Files 0 passed (2)
22
+  Tests 0 passed (0)
23
+  Start at 08:51:08
24
+  Duration 410ms
25
+ [?2026l[?2026h
26
+  ❯ tests/codegen-client.test.ts [queued]
27
+  ❯ tests/codegen-models.test.ts 0/32
28
+
29
+  Test Files 0 passed (2)
30
+  Tests 0 passed (32)
31
+  Start at 08:51:08
32
+  Duration 750ms
33
+ [?2026l[?2026h ✓ tests/codegen-models.test.ts (32 tests) 6ms
34
+
35
+  ❯ tests/codegen-client.test.ts 0/27
36
+
37
+  Test Files 1 passed (2)
38
+  Tests 32 passed (59)
39
+  Start at 08:51:08
40
+  Duration 951ms
41
+ [?2026l ✓ tests/codegen-client.test.ts (27 tests) 9ms
42
+
43
+  Test Files  2 passed (2)
44
+  Tests  59 passed (59)
45
+  Start at  08:51:08
46
+  Duration  1.04s (transform 164ms, setup 0ms, import 968ms, tests 15ms, environment 0ms)
47
+
48
+  % Coverage report from v8
49
+ --------------------|---------|----------|---------|---------|---------------------------------------------------------------------------------------------------
50
+ File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
51
+ --------------------|---------|----------|---------|---------|---------------------------------------------------------------------------------------------------
52
+ All files  |  82.67 |  76.92 |  85.71 |  84.75 |  
53
+  src  |  82.36 |  77.14 |  83.33 |  84.2 |  
54
+  codegen-client.ts |  82.6 |  77.92 |  86.48 |  83.33 | 60-64,139,218,225,246,331-335,345,363-364,372-373,382,405,438,442,458-465,472-473,487-507,540-541
55
+  codegen-models.ts |  82.04 |  75.97 |  79.31 |  85.32 | 51,67-68,91,108-109,137-138,145-154,159-160,166-170,194-195,245,285,307,333,347-349,353 
56
+  tests  |  86.66 |  74.19 |  92 |  92.1 |  
57
+  helpers.ts  |  86.66 |  74.19 |  92 |  92.1 | 137-141,167 
58
+ --------------------|---------|----------|---------|---------|---------------------------------------------------------------------------------------------------
59
+ [?25h
@@ -0,0 +1,15 @@
1
+
2
+ > @contractkit/plugin-python@0.9.0 test /Users/robert/projects/contractkit/packages/plugin-python
3
+ > vitest run
4
+
5
+
6
+  RUN  v4.1.5 /Users/robert/projects/contractkit/packages/plugin-python
7
+
8
+ ✓ tests/codegen-models.test.ts (32 tests) 6ms
9
+ ✓ tests/codegen-client.test.ts (27 tests) 5ms
10
+
11
+  Test Files  2 passed (2)
12
+  Tests  59 passed (59)
13
+  Start at  08:51:33
14
+  Duration  442ms (transform 229ms, setup 0ms, import 563ms, tests 11ms, environment 0ms)
15
+
package/CHANGELOG.md ADDED
@@ -0,0 +1,118 @@
1
+ # @contractkit/contractkit-plugin-python
2
+
3
+ ## 0.9.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 9269093: chore: update dependencies across multiple projects
8
+
9
+ This commit updates various dependencies in the package.json files for several projects, including:
10
+ - Upgraded `@changesets/cli`, `@types/node`, `@vitest/coverage-v8`, `eslint`, `prettier`, `turbo`, and `typescript` to their latest versions.
11
+ - Updated `@types/vscode`, `@vscode/vsce`, and `esbuild` in the vscode extension.
12
+ - Adjusted `@scalar/openapi-parser` and `yaml` in the openapi-to-ck package.
13
+ - Enhanced ESLint and TypeScript configurations in the config-eslint package.
14
+
15
+ These updates improve compatibility and maintainability across the codebase.
16
+
17
+ - Updated dependencies [c9f2166]
18
+ - @contractkit/core@0.11.0
19
+
20
+ ## 0.9.0
21
+
22
+ ### Minor Changes
23
+
24
+ - bbee232: prep for public release
25
+
26
+ ### Patch Changes
27
+
28
+ - Updated dependencies [bbee232]
29
+ - @contractkit/core@0.10.0
30
+
31
+ ## 0.8.0
32
+
33
+ ### Minor Changes
34
+
35
+ - e27b771: Add an `includeInternal: boolean` config option to every plugin so consumers can override whether `internal` operations are emitted. Defaults preserve today's behavior: server router and Bruno default to `true` (include); TS SDK, Python SDK, OpenAPI, and Markdown default to `false` (exclude).
36
+
37
+ ## 0.7.0
38
+
39
+ ### Minor Changes
40
+
41
+ - d13614c: Enhance content type handling in contract DSL. This update introduces support for vendor JSON MIME types and improves the classification of content types, allowing for better handling of text and binary responses. The grammar has been updated to accept a wider range of MIME types, and tests have been added to ensure correct parsing and serialization behavior. Additionally, the code has been refactored to normalize content types for stable comparisons and to support multi-MIME request bodies.
42
+
43
+ ### Patch Changes
44
+
45
+ - Updated dependencies [d13614c]
46
+ - @maroonedsoftware/contractkit@0.9.0
47
+
48
+ ## 0.6.0
49
+
50
+ ### Minor Changes
51
+
52
+ - 888ded5: Enhance contract DSL with multi-base inheritance support and override modifier. This update introduces the ability to declare multiple base contracts, along with validation rules for field conflicts across bases. The `override` modifier is now required for redeclaring conflicting fields, and the documentation has been updated to reflect these changes. Tests have been added to ensure correct behavior for inheritance and modifier usage.
53
+
54
+ ### Patch Changes
55
+
56
+ - Updated dependencies [353aa10]
57
+ - Updated dependencies [888ded5]
58
+ - @maroonedsoftware/contractkit@0.8.0
59
+
60
+ ## 0.5.0
61
+
62
+ ### Minor Changes
63
+
64
+ - 5d42e39: Enhance Python and TypeScript SDKs to support typed response headers. Updated the Python client to generate `TypedDict` for response headers and modified return types accordingly. The TypeScript SDK now includes runtime assertions for required headers and documents them in the generated markdown. Tests were added to verify the correct handling of response headers in both SDKs.
65
+
66
+ ## 0.4.2
67
+
68
+ ### Patch Changes
69
+
70
+ - Updated dependencies [16ac3a7]
71
+ - @maroonedsoftware/contractkit@0.7.0
72
+
73
+ ## 0.4.1
74
+
75
+ ### Patch Changes
76
+
77
+ - Updated dependencies [d3ea773]
78
+ - @maroonedsoftware/contractkit@0.6.0
79
+
80
+ ## 0.4.0
81
+
82
+ ### Minor Changes
83
+
84
+ - 181dadb: Refactor request handling to support multiple content types in operations. Updated OpRequestNode to accept an array of bodies, modified related functions and tests to accommodate multi-MIME requests, and enhanced validation for nested structures in URL-encoded bodies. Improved code generation across various plugins to handle new request structure.
85
+
86
+ ### Patch Changes
87
+
88
+ - Updated dependencies [181dadb]
89
+ - @maroonedsoftware/contractkit@0.5.0
90
+
91
+ ## 0.3.0
92
+
93
+ ### Minor Changes
94
+
95
+ - ada5f84: Implement discriminated unions in ContractKit with validation and code generation support. Update README and tests to reflect new functionality, including parsing, rendering, and OpenAPI generation for discriminated unions.
96
+
97
+ ### Patch Changes
98
+
99
+ - Updated dependencies [ada5f84]
100
+ - @maroonedsoftware/contractkit@0.4.0
101
+
102
+ ## 0.2.1
103
+
104
+ ### Patch Changes
105
+
106
+ - Updated dependencies [f396a68]
107
+ - @maroonedsoftware/contractkit@0.3.0
108
+
109
+ ## 0.2.0
110
+
111
+ ### Minor Changes
112
+
113
+ - db7345b: updating to contractkit as the org
114
+
115
+ ### Patch Changes
116
+
117
+ - Updated dependencies [db7345b]
118
+ - @contractkit/core@0.2.0
package/README.md ADDED
@@ -0,0 +1,86 @@
1
+ # @contractkit/contractkit-plugin-python-sdk
2
+
3
+ ContractKit plugin that generates a Python SDK from `.ck` contract and operation files. Produces [Pydantic v2](https://docs.pydantic.dev/latest/) models and [httpx](https://www.python-httpx.org/)-based client classes.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @contractkit/contractkit-plugin-python-sdk
9
+ ```
10
+
11
+ ## Configuration
12
+
13
+ ```json
14
+ {
15
+ "plugins": {
16
+ "@contractkit/contractkit-plugin-python-sdk": {
17
+ "baseDir": "python-sdk",
18
+ "packageName": "acme"
19
+ }
20
+ }
21
+ }
22
+ ```
23
+
24
+ ## Options
25
+
26
+ | Option | Type | Default | Description |
27
+ |---|---|---|---|
28
+ | `baseDir` | `string` | `"python-sdk"` | Output directory relative to rootDir |
29
+ | `packageName` | `string` | `"Sdk"` | Name used for the aggregator SDK class |
30
+
31
+ ## Output structure
32
+
33
+ ```
34
+ python-sdk/
35
+ ├── __init__.py # SDK aggregator class + __all__ exports
36
+ ├── _base_client.py # Shared BaseClient and SdkError classes
37
+ ├── _models_<name>.py # Pydantic v2 models (one file per .ck contract file)
38
+ ├── _client_<name>.py # httpx client class (one file per .ck operation file)
39
+ └── requirements.txt # Runtime dependencies (httpx, pydantic>=2.0)
40
+ ```
41
+
42
+ ### Models (`_models_*.py`)
43
+
44
+ Each `contract` declaration becomes a Pydantic v2 `BaseModel`. Contracts that have `readonly` or `writeonly` fields produce separate Input variants following the same rules as the TypeScript plugin:
45
+
46
+ - **`Model`** — read model (no writeonly fields)
47
+ - **`ModelInput`** — input model (no readonly fields)
48
+
49
+ ### Clients (`_client_*.py`)
50
+
51
+ Each operation file with at least one public operation generates a client class. Methods correspond to HTTP verbs and are named from the `sdk:` field in the `.ck` source. Request and response bodies are typed with the generated Pydantic models.
52
+
53
+ ### Aggregator (`__init__.py`)
54
+
55
+ The aggregator class (named from `packageName`) instantiates all client classes and exposes them as attributes. Pass the base URL and optional headers at construction time:
56
+
57
+ ```python
58
+ from python_sdk import AcmeSdk
59
+
60
+ sdk = AcmeSdk(base_url="https://api.acme.com", headers={"Authorization": "Bearer ..."})
61
+ payment = sdk.payments.get_payment(id="pay_123")
62
+ ```
63
+
64
+ ### Base client (`_base_client.py`)
65
+
66
+ Provides `BaseClient` (wraps `httpx.Client`) and `SdkError` (raised on non-2xx responses). All generated client classes inherit from `BaseClient`.
67
+
68
+ ## Runtime dependencies
69
+
70
+ The generated SDK requires:
71
+
72
+ ```
73
+ pydantic>=2.0
74
+ httpx
75
+ ```
76
+
77
+ ## Programmatic use
78
+
79
+ ```typescript
80
+ import { createPythonSdkPlugin } from '@contractkit/contractkit-plugin-python-sdk';
81
+
82
+ const plugin = createPythonSdkPlugin({
83
+ baseDir: 'sdks/python',
84
+ packageName: 'acme',
85
+ });
86
+ ```
@@ -0,0 +1,224 @@
1
+ body, html {
2
+ margin:0; padding: 0;
3
+ height: 100%;
4
+ }
5
+ body {
6
+ font-family: Helvetica Neue, Helvetica, Arial;
7
+ font-size: 14px;
8
+ color:#333;
9
+ }
10
+ .small { font-size: 12px; }
11
+ *, *:after, *:before {
12
+ -webkit-box-sizing:border-box;
13
+ -moz-box-sizing:border-box;
14
+ box-sizing:border-box;
15
+ }
16
+ h1 { font-size: 20px; margin: 0;}
17
+ h2 { font-size: 14px; }
18
+ pre {
19
+ font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace;
20
+ margin: 0;
21
+ padding: 0;
22
+ -moz-tab-size: 2;
23
+ -o-tab-size: 2;
24
+ tab-size: 2;
25
+ }
26
+ a { color:#0074D9; text-decoration:none; }
27
+ a:hover { text-decoration:underline; }
28
+ .strong { font-weight: bold; }
29
+ .space-top1 { padding: 10px 0 0 0; }
30
+ .pad2y { padding: 20px 0; }
31
+ .pad1y { padding: 10px 0; }
32
+ .pad2x { padding: 0 20px; }
33
+ .pad2 { padding: 20px; }
34
+ .pad1 { padding: 10px; }
35
+ .space-left2 { padding-left:55px; }
36
+ .space-right2 { padding-right:20px; }
37
+ .center { text-align:center; }
38
+ .clearfix { display:block; }
39
+ .clearfix:after {
40
+ content:'';
41
+ display:block;
42
+ height:0;
43
+ clear:both;
44
+ visibility:hidden;
45
+ }
46
+ .fl { float: left; }
47
+ @media only screen and (max-width:640px) {
48
+ .col3 { width:100%; max-width:100%; }
49
+ .hide-mobile { display:none!important; }
50
+ }
51
+
52
+ .quiet {
53
+ color: #7f7f7f;
54
+ color: rgba(0,0,0,0.5);
55
+ }
56
+ .quiet a { opacity: 0.7; }
57
+
58
+ .fraction {
59
+ font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
60
+ font-size: 10px;
61
+ color: #555;
62
+ background: #E8E8E8;
63
+ padding: 4px 5px;
64
+ border-radius: 3px;
65
+ vertical-align: middle;
66
+ }
67
+
68
+ div.path a:link, div.path a:visited { color: #333; }
69
+ table.coverage {
70
+ border-collapse: collapse;
71
+ margin: 10px 0 0 0;
72
+ padding: 0;
73
+ }
74
+
75
+ table.coverage td {
76
+ margin: 0;
77
+ padding: 0;
78
+ vertical-align: top;
79
+ }
80
+ table.coverage td.line-count {
81
+ text-align: right;
82
+ padding: 0 5px 0 20px;
83
+ }
84
+ table.coverage td.line-coverage {
85
+ text-align: right;
86
+ padding-right: 10px;
87
+ min-width:20px;
88
+ }
89
+
90
+ table.coverage td span.cline-any {
91
+ display: inline-block;
92
+ padding: 0 5px;
93
+ width: 100%;
94
+ }
95
+ .missing-if-branch {
96
+ display: inline-block;
97
+ margin-right: 5px;
98
+ border-radius: 3px;
99
+ position: relative;
100
+ padding: 0 4px;
101
+ background: #333;
102
+ color: yellow;
103
+ }
104
+
105
+ .skip-if-branch {
106
+ display: none;
107
+ margin-right: 10px;
108
+ position: relative;
109
+ padding: 0 4px;
110
+ background: #ccc;
111
+ color: white;
112
+ }
113
+ .missing-if-branch .typ, .skip-if-branch .typ {
114
+ color: inherit !important;
115
+ }
116
+ .coverage-summary {
117
+ border-collapse: collapse;
118
+ width: 100%;
119
+ }
120
+ .coverage-summary tr { border-bottom: 1px solid #bbb; }
121
+ .keyline-all { border: 1px solid #ddd; }
122
+ .coverage-summary td, .coverage-summary th { padding: 10px; }
123
+ .coverage-summary tbody { border: 1px solid #bbb; }
124
+ .coverage-summary td { border-right: 1px solid #bbb; }
125
+ .coverage-summary td:last-child { border-right: none; }
126
+ .coverage-summary th {
127
+ text-align: left;
128
+ font-weight: normal;
129
+ white-space: nowrap;
130
+ }
131
+ .coverage-summary th.file { border-right: none !important; }
132
+ .coverage-summary th.pct { }
133
+ .coverage-summary th.pic,
134
+ .coverage-summary th.abs,
135
+ .coverage-summary td.pct,
136
+ .coverage-summary td.abs { text-align: right; }
137
+ .coverage-summary td.file { white-space: nowrap; }
138
+ .coverage-summary td.pic { min-width: 120px !important; }
139
+ .coverage-summary tfoot td { }
140
+
141
+ .coverage-summary .sorter {
142
+ height: 10px;
143
+ width: 7px;
144
+ display: inline-block;
145
+ margin-left: 0.5em;
146
+ background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
147
+ }
148
+ .coverage-summary .sorted .sorter {
149
+ background-position: 0 -20px;
150
+ }
151
+ .coverage-summary .sorted-desc .sorter {
152
+ background-position: 0 -10px;
153
+ }
154
+ .status-line { height: 10px; }
155
+ /* yellow */
156
+ .cbranch-no { background: yellow !important; color: #111; }
157
+ /* dark red */
158
+ .red.solid, .status-line.low, .low .cover-fill { background:#C21F39 }
159
+ .low .chart { border:1px solid #C21F39 }
160
+ .highlighted,
161
+ .highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{
162
+ background: #C21F39 !important;
163
+ }
164
+ /* medium red */
165
+ .cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE }
166
+ /* light red */
167
+ .low, .cline-no { background:#FCE1E5 }
168
+ /* light green */
169
+ .high, .cline-yes { background:rgb(230,245,208) }
170
+ /* medium green */
171
+ .cstat-yes { background:rgb(161,215,106) }
172
+ /* dark green */
173
+ .status-line.high, .high .cover-fill { background:rgb(77,146,33) }
174
+ .high .chart { border:1px solid rgb(77,146,33) }
175
+ /* dark yellow (gold) */
176
+ .status-line.medium, .medium .cover-fill { background: #f9cd0b; }
177
+ .medium .chart { border:1px solid #f9cd0b; }
178
+ /* light yellow */
179
+ .medium { background: #fff4c2; }
180
+
181
+ .cstat-skip { background: #ddd; color: #111; }
182
+ .fstat-skip { background: #ddd; color: #111 !important; }
183
+ .cbranch-skip { background: #ddd !important; color: #111; }
184
+
185
+ span.cline-neutral { background: #eaeaea; }
186
+
187
+ .coverage-summary td.empty {
188
+ opacity: .5;
189
+ padding-top: 4px;
190
+ padding-bottom: 4px;
191
+ line-height: 1;
192
+ color: #888;
193
+ }
194
+
195
+ .cover-fill, .cover-empty {
196
+ display:inline-block;
197
+ height: 12px;
198
+ }
199
+ .chart {
200
+ line-height: 0;
201
+ }
202
+ .cover-empty {
203
+ background: white;
204
+ }
205
+ .cover-full {
206
+ border-right: none !important;
207
+ }
208
+ pre.prettyprint {
209
+ border: none !important;
210
+ padding: 0 !important;
211
+ margin: 0 !important;
212
+ }
213
+ .com { color: #999 !important; }
214
+ .ignore-none { color: #999; font-weight: normal; }
215
+
216
+ .wrapper {
217
+ min-height: 100%;
218
+ height: auto !important;
219
+ height: 100%;
220
+ margin: 0 auto -48px;
221
+ }
222
+ .footer, .push {
223
+ height: 48px;
224
+ }
@@ -0,0 +1,87 @@
1
+ /* eslint-disable */
2
+ var jumpToCode = (function init() {
3
+ // Classes of code we would like to highlight in the file view
4
+ var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no'];
5
+
6
+ // Elements to highlight in the file listing view
7
+ var fileListingElements = ['td.pct.low'];
8
+
9
+ // We don't want to select elements that are direct descendants of another match
10
+ var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > `
11
+
12
+ // Selector that finds elements on the page to which we can jump
13
+ var selector =
14
+ fileListingElements.join(', ') +
15
+ ', ' +
16
+ notSelector +
17
+ missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b`
18
+
19
+ // The NodeList of matching elements
20
+ var missingCoverageElements = document.querySelectorAll(selector);
21
+
22
+ var currentIndex;
23
+
24
+ function toggleClass(index) {
25
+ missingCoverageElements
26
+ .item(currentIndex)
27
+ .classList.remove('highlighted');
28
+ missingCoverageElements.item(index).classList.add('highlighted');
29
+ }
30
+
31
+ function makeCurrent(index) {
32
+ toggleClass(index);
33
+ currentIndex = index;
34
+ missingCoverageElements.item(index).scrollIntoView({
35
+ behavior: 'smooth',
36
+ block: 'center',
37
+ inline: 'center'
38
+ });
39
+ }
40
+
41
+ function goToPrevious() {
42
+ var nextIndex = 0;
43
+ if (typeof currentIndex !== 'number' || currentIndex === 0) {
44
+ nextIndex = missingCoverageElements.length - 1;
45
+ } else if (missingCoverageElements.length > 1) {
46
+ nextIndex = currentIndex - 1;
47
+ }
48
+
49
+ makeCurrent(nextIndex);
50
+ }
51
+
52
+ function goToNext() {
53
+ var nextIndex = 0;
54
+
55
+ if (
56
+ typeof currentIndex === 'number' &&
57
+ currentIndex < missingCoverageElements.length - 1
58
+ ) {
59
+ nextIndex = currentIndex + 1;
60
+ }
61
+
62
+ makeCurrent(nextIndex);
63
+ }
64
+
65
+ return function jump(event) {
66
+ if (
67
+ document.getElementById('fileSearch') === document.activeElement &&
68
+ document.activeElement != null
69
+ ) {
70
+ // if we're currently focused on the search input, we don't want to navigate
71
+ return;
72
+ }
73
+
74
+ switch (event.which) {
75
+ case 78: // n
76
+ case 74: // j
77
+ goToNext();
78
+ break;
79
+ case 66: // b
80
+ case 75: // k
81
+ case 80: // p
82
+ goToPrevious();
83
+ break;
84
+ }
85
+ };
86
+ })();
87
+ window.addEventListener('keydown', jumpToCode);