@contractkit/plugin-openapi 0.8.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 (42) 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 +105 -0
  4. package/.turbo/turbo-test.log +14 -0
  5. package/CHANGELOG.md +103 -0
  6. package/README.md +78 -0
  7. package/coverage/base.css +224 -0
  8. package/coverage/block-navigation.js +87 -0
  9. package/coverage/clover.xml +403 -0
  10. package/coverage/coverage-final.json +3 -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-openapi.ts.html +2308 -0
  18. package/coverage/src/index.html +116 -0
  19. package/coverage/tests/helpers.ts.html +616 -0
  20. package/coverage/tests/index.html +116 -0
  21. package/dist/codegen-openapi.d.ts +44 -0
  22. package/dist/codegen-openapi.d.ts.map +1 -0
  23. package/dist/index.d.ts +10 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +701 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/src/codegen-openapi.d.ts +38 -0
  28. package/dist/src/codegen-openapi.d.ts.map +1 -0
  29. package/dist/src/index.d.ts +4 -0
  30. package/dist/src/index.d.ts.map +1 -0
  31. package/dist/tests/codegen-openapi.test.d.ts +2 -0
  32. package/dist/tests/codegen-openapi.test.d.ts.map +1 -0
  33. package/dist/tests/helpers.d.ts +31 -0
  34. package/dist/tests/helpers.d.ts.map +1 -0
  35. package/eslint.config.js +6 -0
  36. package/package.json +43 -0
  37. package/src/codegen-openapi.ts +741 -0
  38. package/src/index.ts +43 -0
  39. package/tests/codegen-openapi.test.ts +767 -0
  40. package/tests/helpers.ts +177 -0
  41. package/tsconfig.json +9 -0
  42. package/vitest.config.ts +14 -0
@@ -0,0 +1,35 @@
1
+
2
+ 
3
+ > @contractkit/plugin-openapi@0.8.0 build:ci /Users/robert/projects/contractkit/packages/plugin-openapi
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-openapi@0.8.0 build /Users/robert/projects/contractkit/packages/plugin-openapi
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 19.85 KB
31
+ ESM dist/index.js.map 44.92 KB
32
+ ESM ⚡️ Build success in 38ms
33
+ DTS Build start
34
+ DTS ⚡️ Build success in 657ms
35
+ DTS dist/index.d.ts 1.33 KB
@@ -0,0 +1,15 @@
1
+
2
+ > @contractkit/plugin-openapi@0.8.0 build /Users/robert/projects/contractkit/packages/plugin-openapi
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 19.85 KB
11
+ ESM dist/index.js.map 44.92 KB
12
+ ESM ⚡️ Build success in 60ms
13
+ DTS Build start
14
+ DTS ⚡️ Build success in 671ms
15
+ DTS dist/index.d.ts 1.33 KB
@@ -0,0 +1,105 @@
1
+
2
+ 
3
+ > @contractkit/plugin-openapi@0.8.0 test:ci /Users/robert/projects/contractkit/packages/plugin-openapi
4
+ > vitest run --coverage
5
+
6
+ [?25l
7
+  RUN  v4.1.5 /Users/robert/projects/contractkit/packages/plugin-openapi
8
+ Coverage enabled with v8
9
+
10
+ [?2026h
11
+  ❯ tests/codegen-openapi.test.ts [queued]
12
+
13
+  Test Files 0 passed (1)
14
+  Tests 0 passed (0)
15
+  Start at 08:51:09
16
+  Duration 204ms
17
+ [?2026l[?2026h
18
+  ❯ tests/codegen-openapi.test.ts 0/53
19
+
20
+  Test Files 0 passed (1)
21
+  Tests 0 passed (53)
22
+  Start at 08:51:09
23
+  Duration 863ms
24
+ [?2026l ✓ tests/codegen-openapi.test.ts (53 tests) 46ms
25
+ ✓ toYaml (8)
26
+ ✓ serializes simple scalars 1ms
27
+ ✓ quotes strings that look like YAML reserved words 0ms
28
+ ✓ quotes empty strings 0ms
29
+ ✓ quotes strings starting with digits 0ms
30
+ ✓ serializes flat objects 0ms
31
+ ✓ serializes nested objects 3ms
32
+ ✓ serializes simple arrays inline 1ms
33
+ ✓ serializes object arrays as block sequences 0ms
34
+ ✓ generateOpenApi (31)
35
+ ✓ document structure (5)
36
+ ✓ generates openapi 3.1.0 header 0ms
37
+ ✓ uses config info values 0ms
38
+ ✓ defaults title and version when not specified 0ms
39
+ ✓ includes servers when configured 0ms
40
+ ✓ includes security when configured 10ms
41
+ ✓ component schemas (12)
42
+ ✓ generates schema for simple model 6ms
43
+ ✓ handles optional fields by omitting from required 1ms
44
+ ✓ marks readonly/writeonly fields 1ms
45
+ ✓ handles default values 0ms
46
+ ✓ generates enum schema 0ms
47
+ ✓ generates array field schema 0ms
48
+ ✓ generates model with base (allOf) 0ms
49
+ ✓ emits one $ref per base for multi-base inheritance 0ms
50
+ ✓ handles scalar type constraints 0ms
51
+ ✓ handles record type 0ms
52
+ ✓ handles description on models and fields 0ms
53
+ ✓ emits oneOf with a discriminator block for discriminated unions 1ms
54
+ ✓ paths (12)
55
+ ✓ converts :param to {param} in paths 0ms
56
+ ✓ generates GET operation 0ms
57
+ ✓ generates POST with request body 0ms
58
+ ✓ generates path parameters 0ms
59
+ ✓ generates query parameters 0ms
60
+ ✓ generates header parameters 0ms
61
+ ✓ uses operationId from service binding 0ms
62
+ ✓ uses operationId from sdk name 0ms
63
+ ✓ generates 204 No content response 0ms
64
+ ✓ includes operation description 0ms
65
+ ✓ emits response headers 0ms
66
+ ✓ handles inline object response body 0ms
67
+ ✓ combining multiple files (2)
68
+ ✓ merges paths from multiple op files 0ms
69
+ ✓ merges schemas from multiple contract files 0ms
70
+ ✓ route modifiers (11)
71
+ ✓ internal (4)
72
+ ✓ excludes an internal operation from paths 0ms
73
+ ✓ includes internal operations when config.includeInternal is true 0ms
74
+ ✓ excludes all operations when route is internal 0ms
75
+ ✓ operation-level override on internal route makes that operation visible 0ms
76
+ ✓ schema filtering — internal operations (4)
77
+ ✓ excludes schemas only referenced by internal operations 0ms
78
+ ✓ transitively includes schemas referenced by public types 0ms
79
+ ✓ excludes all schemas when all operations are internal 0ms
80
+ ✓ includes all schemas when there are no op files 0ms
81
+ ✓ deprecated (3)
82
+ ✓ sets deprecated: true for a deprecated operation 0ms
83
+ ✓ does not set deprecated for a normal operation 0ms
84
+ ✓ cascades route-level deprecated to all operations 0ms
85
+ ✓ options-level header globals (3)
86
+ ✓ renders global response headers on every status code, including bodyless and 4xx/5xx 3ms
87
+ ✓ omits global response headers on a status code that opts out via headers: none 1ms
88
+ ✓ renders global request headers as parameters on every operation 9ms
89
+
90
+  Test Files  1 passed (1)
91
+  Tests  53 passed (53)
92
+  Start at  08:51:09
93
+  Duration  1.02s (transform 161ms, setup 0ms, import 651ms, tests 46ms, environment 0ms)
94
+
95
+  % Coverage report from v8
96
+ ---------------------|---------|----------|---------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------
97
+ File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
98
+ ---------------------|---------|----------|---------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------
99
+ All files  |  78.88 |  74.52 |  82.25 |  81.03 |  
100
+  src  |  79.5 |  75.26 |  86.11 |  81.5 |  
101
+  codegen-openapi.ts |  79.5 |  75.26 |  86.11 |  81.5 | 56-60,67-68,78-79,85,278,288,302,315,323,345,351,363-364,376-377,382-385,392-394,399-409,415-417,424-437,468-474,525,567,588-609,669-672,696,706
102
+  tests  |  73.33 |  67.74 |  76.92 |  76.92 |  
103
+  helpers.ts  |  73.33 |  67.74 |  76.92 |  76.92 | 44,60,76,110-118,138,149-150 
104
+ ---------------------|---------|----------|---------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------
105
+ [?25h
@@ -0,0 +1,14 @@
1
+
2
+ > @contractkit/plugin-openapi@0.8.0 test /Users/robert/projects/contractkit/packages/plugin-openapi
3
+ > vitest run
4
+
5
+
6
+  RUN  v4.1.5 /Users/robert/projects/contractkit/packages/plugin-openapi
7
+
8
+ ✓ tests/codegen-openapi.test.ts (53 tests) 11ms
9
+
10
+  Test Files  1 passed (1)
11
+  Tests  53 passed (53)
12
+  Start at  08:51:33
13
+  Duration  418ms (transform 180ms, setup 0ms, import 274ms, tests 11ms, environment 0ms)
14
+
package/CHANGELOG.md ADDED
@@ -0,0 +1,103 @@
1
+ # @contractkit/contractkit-plugin-openapi
2
+
3
+ ## 0.8.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [c9f2166]
8
+ - @contractkit/core@0.11.0
9
+
10
+ ## 0.8.0
11
+
12
+ ### Minor Changes
13
+
14
+ - bbee232: prep for public release
15
+
16
+ ### Patch Changes
17
+
18
+ - Updated dependencies [bbee232]
19
+ - @contractkit/core@0.10.0
20
+
21
+ ## 0.7.0
22
+
23
+ ### Minor Changes
24
+
25
+ - 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).
26
+
27
+ ## 0.6.1
28
+
29
+ ### Patch Changes
30
+
31
+ - Updated dependencies [d13614c]
32
+ - @maroonedsoftware/contractkit@0.9.0
33
+
34
+ ## 0.6.0
35
+
36
+ ### Minor Changes
37
+
38
+ - 353aa10: Implement options-level header globals for request and response in the contract DSL. This update allows headers to be declared at the file level, merging them into every operation's request and response. Added normalization logic to handle header collisions and opt-out scenarios. Updated documentation and tests to reflect these changes, ensuring proper round-trip formatting and validation of headers.
39
+ - 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.
40
+
41
+ ### Patch Changes
42
+
43
+ - Updated dependencies [353aa10]
44
+ - Updated dependencies [888ded5]
45
+ - @maroonedsoftware/contractkit@0.8.0
46
+
47
+ ## 0.5.0
48
+
49
+ ### Minor Changes
50
+
51
+ - 16ac3a7: Implement support for typed response headers in API operations. Added functionality to declare headers alongside response bodies, affecting OpenAPI, TypeScript SDK, and Markdown documentation generation. Updated related tests to ensure correct parsing and rendering of response headers, including handling optional headers and duplicate declarations.
52
+
53
+ ### Patch Changes
54
+
55
+ - Updated dependencies [16ac3a7]
56
+ - @maroonedsoftware/contractkit@0.7.0
57
+
58
+ ## 0.4.1
59
+
60
+ ### Patch Changes
61
+
62
+ - Updated dependencies [d3ea773]
63
+ - @maroonedsoftware/contractkit@0.6.0
64
+
65
+ ## 0.4.0
66
+
67
+ ### Minor Changes
68
+
69
+ - 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.
70
+
71
+ ### Patch Changes
72
+
73
+ - Updated dependencies [181dadb]
74
+ - @maroonedsoftware/contractkit@0.5.0
75
+
76
+ ## 0.3.0
77
+
78
+ ### Minor Changes
79
+
80
+ - 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.
81
+
82
+ ### Patch Changes
83
+
84
+ - Updated dependencies [ada5f84]
85
+ - @maroonedsoftware/contractkit@0.4.0
86
+
87
+ ## 0.2.1
88
+
89
+ ### Patch Changes
90
+
91
+ - Updated dependencies [f396a68]
92
+ - @maroonedsoftware/contractkit@0.3.0
93
+
94
+ ## 0.2.0
95
+
96
+ ### Minor Changes
97
+
98
+ - db7345b: updating to contractkit as the org
99
+
100
+ ### Patch Changes
101
+
102
+ - Updated dependencies [db7345b]
103
+ - @contractkit/core@0.2.0
package/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # @contractkit/contractkit-plugin-openapi
2
+
3
+ ContractKit plugin that generates an OpenAPI 3.0 YAML specification from `.ck` contract and operation files.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @contractkit/contractkit-plugin-openapi
9
+ ```
10
+
11
+ ## Configuration
12
+
13
+ ```json
14
+ {
15
+ "plugins": {
16
+ "@contractkit/contractkit-plugin-openapi": {
17
+ "output": "openapi.yaml",
18
+ "info": {
19
+ "title": "Acme API",
20
+ "version": "1.0.0",
21
+ "description": "Public API for Acme services"
22
+ },
23
+ "servers": [
24
+ { "url": "https://api.acme.com", "description": "Production" },
25
+ { "url": "https://api.staging.acme.com", "description": "Staging" }
26
+ ],
27
+ "security": [{ "bearerAuth": [] }],
28
+ "securitySchemes": {
29
+ "bearerAuth": {
30
+ "type": "http",
31
+ "scheme": "bearer",
32
+ "bearerFormat": "JWT"
33
+ }
34
+ }
35
+ }
36
+ }
37
+ }
38
+ ```
39
+
40
+ ## Options
41
+
42
+ | Option | Type | Default | Description |
43
+ |---|---|---|---|
44
+ | `baseDir` | `string` | `rootDir` | Base directory for the output file |
45
+ | `output` | `string` | `"openapi.yaml"` | Output file path |
46
+ | `info.title` | `string` | — | API title in the `info` block |
47
+ | `info.version` | `string` | — | API version in the `info` block |
48
+ | `info.description` | `string` | — | API description in the `info` block |
49
+ | `servers` | `array` | — | List of server objects (`url`, optional `description`) |
50
+ | `security` | `array` | — | Global security requirements (e.g. `[{ "bearerAuth": [] }]`) |
51
+ | `securitySchemes` | `object` | — | Security scheme definitions added to `components.securitySchemes` |
52
+
53
+ ### Security scheme types
54
+
55
+ | `type` | Required fields | Description |
56
+ |---|---|---|
57
+ | `"http"` | `scheme` (`"bearer"` or `"basic"`), optional `bearerFormat` | HTTP auth (Bearer JWT, Basic, etc.) |
58
+ | `"apiKey"` | `name`, `in` (`"header"` or `"query"`) | API key passed in a header or query param |
59
+ | `"oauth2"` | — | OAuth 2.0 |
60
+ | `"openIdConnect"` | — | OpenID Connect |
61
+
62
+ ## Output
63
+
64
+ The plugin writes a single YAML file. All `contract` declarations become entries in `components/schemas`. All `operation` declarations become paths with their HTTP verbs, request bodies, parameters, and response schemas.
65
+
66
+ Operations marked `internal` are omitted from the generated spec by default. Set `includeInternal: true` in the plugin config to include them (e.g. for an internal-use API spec).
67
+
68
+ ## Programmatic use
69
+
70
+ ```typescript
71
+ import { createOpenApiPlugin } from '@contractkit/contractkit-plugin-openapi';
72
+
73
+ const plugin = createOpenApiPlugin({
74
+ output: 'dist/openapi.yaml',
75
+ info: { title: 'My API', version: '2.0.0' },
76
+ servers: [{ url: 'https://api.example.com' }],
77
+ });
78
+ ```
@@ -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);