simplecov 1.0.0.rc4 → 1.0.0.rc5
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.
- checksums.yaml +4 -4
- data/lib/simplecov/formatter/html_formatter/public/application.css +1 -1
- data/lib/simplecov/formatter/html_formatter/public/application.js +8 -8
- data/lib/simplecov/formatter/json_formatter/result_hash_formatter.rb +2 -1
- data/lib/simplecov/parallel_adapters/base.rb +10 -0
- data/lib/simplecov/parallel_adapters/parallel_tests.rb +6 -0
- data/lib/simplecov/parallel_coordination.rb +44 -8
- data/lib/simplecov/version.rb +1 -1
- data/schemas/coverage-v1.0.schema.json +6 -0
- data/schemas/coverage.schema.json +6 -0
- metadata +3 -4
- data/CHANGELOG.md +0 -305
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 366e4616ba75b475d6946a6002342f4ac1334d52b7dee3ae527c2a6d48314600
|
|
4
|
+
data.tar.gz: cf4b78bdd20a358f8373c1ab81ac5424581b53596162370acfe2a93ad08852a5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e0249e3ddcc1fa221b1476113755eff077f3ceb8840048bbe1752f14b5e9ba226c70eb8f23ae2d212e9d7fe9b2ec3488a96a86cfb11fb0b16d49483264f0e068
|
|
7
|
+
data.tar.gz: a8ae34d4a8712475fa9ce3f14619f1fa5ea75769b1510a77921a2b6aa101fe073c9dda4b99aaf54f24b84a1116f98ebb5088699dd2830e971dafe98b82de4fdd
|
|
@@ -1 +1 @@
|
|
|
1
|
-
*,*:before,*:after{box-sizing:border-box}*{margin:0;padding:0}html{-moz-text-size-adjust:none;-webkit-text-size-adjust:none;text-size-adjust:none}body{min-height:100vh;line-height:1.5;-webkit-font-smoothing:antialiased}img,picture,svg{display:block;max-width:100%}input,button,textarea,select{font:inherit}h1,h2,h3,h4,h5,h6{overflow-wrap:break-word;text-wrap:balance}p{overflow-wrap:break-word;text-wrap:pretty}table{border-collapse:collapse;border-spacing:0}ul,ol{list-style:none}a{text-decoration-skip-ink:auto;color:currentColor}.hide{display:none}.hljs{color:#24292e}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#005cc5}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-comment,.hljs-code,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}@media(prefers-color-scheme:dark){:root:not(.light-mode) .hljs{color:#c9d1d9}:root:not(.light-mode) .hljs-doctag,:root:not(.light-mode) .hljs-keyword,:root:not(.light-mode) .hljs-meta .hljs-keyword,:root:not(.light-mode) .hljs-template-tag,:root:not(.light-mode) .hljs-template-variable,:root:not(.light-mode) .hljs-type,:root:not(.light-mode) .hljs-variable.language_{color:#ff7b72}:root:not(.light-mode) .hljs-title,:root:not(.light-mode) .hljs-title.class_,:root:not(.light-mode) .hljs-title.class_.inherited__,:root:not(.light-mode) .hljs-title.function_{color:#d2a8ff}:root:not(.light-mode) .hljs-attr,:root:not(.light-mode) .hljs-attribute,:root:not(.light-mode) .hljs-literal,:root:not(.light-mode) .hljs-meta,:root:not(.light-mode) .hljs-number,:root:not(.light-mode) .hljs-operator,:root:not(.light-mode) .hljs-variable,:root:not(.light-mode) .hljs-selector-attr,:root:not(.light-mode) .hljs-selector-class,:root:not(.light-mode) .hljs-selector-id{color:#79c0ff}:root:not(.light-mode) .hljs-regexp,:root:not(.light-mode) .hljs-string,:root:not(.light-mode) .hljs-meta .hljs-string{color:#a5d6ff}:root:not(.light-mode) .hljs-built_in,:root:not(.light-mode) .hljs-symbol{color:#ffa657}:root:not(.light-mode) .hljs-comment,:root:not(.light-mode) .hljs-code,:root:not(.light-mode) .hljs-formula{color:#8b949e}:root:not(.light-mode) .hljs-name,:root:not(.light-mode) .hljs-quote,:root:not(.light-mode) .hljs-selector-tag,:root:not(.light-mode) .hljs-selector-pseudo{color:#7ee787}:root:not(.light-mode) .hljs-subst{color:#c9d1d9}:root:not(.light-mode) .hljs-section{color:#1f6feb}}.dark-mode .hljs{color:#c9d1d9}.dark-mode .hljs-doctag,.dark-mode .hljs-keyword,.dark-mode .hljs-meta .hljs-keyword,.dark-mode .hljs-template-tag,.dark-mode .hljs-template-variable,.dark-mode .hljs-type,.dark-mode .hljs-variable.language_{color:#ff7b72}.dark-mode .hljs-title,.dark-mode .hljs-title.class_,.dark-mode .hljs-title.class_.inherited__,.dark-mode .hljs-title.function_{color:#d2a8ff}.dark-mode .hljs-attr,.dark-mode .hljs-attribute,.dark-mode .hljs-literal,.dark-mode .hljs-meta,.dark-mode .hljs-number,.dark-mode .hljs-operator,.dark-mode .hljs-variable,.dark-mode .hljs-selector-attr,.dark-mode .hljs-selector-class,.dark-mode .hljs-selector-id{color:#79c0ff}.dark-mode .hljs-regexp,.dark-mode .hljs-string,.dark-mode .hljs-meta .hljs-string{color:#a5d6ff}.dark-mode .hljs-built_in,.dark-mode .hljs-symbol{color:#ffa657}.dark-mode .hljs-comment,.dark-mode .hljs-code,.dark-mode .hljs-formula{color:#8b949e}.dark-mode .hljs-name,.dark-mode .hljs-quote,.dark-mode .hljs-selector-tag,.dark-mode .hljs-selector-pseudo{color:#7ee787}.dark-mode .hljs-subst{color:#c9d1d9}.dark-mode .hljs-section{color:#1f6feb}:root{--font-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--font-mono: ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, Consolas, "DejaVu Sans Mono", monospace;--sp-1: 4px;--sp-2: 8px;--sp-3: 12px;--sp-4: 16px;--sp-5: 20px;--sp-6: 24px;--sp-8: 32px;--radius-sm: 8px;--radius-md: 12px;--radius-lg: 16px;--bg: #f0f1f3;--surface: #fff;--surface-alt: #f0f1f3;--text: #111;--text-secondary: #333;--text-tertiary: #444;--zebra: #f4f5f7;--border: #c0c5cc;--border-strong: #999;--accent: #0550ae;--accent-hover: #033d8b;--accent-subtle: #ddf4ff;--green: #116329;--red: #a40e26;--yellow: #7a5200;--orange: #953800;--covered-bg: #ccf5d0;--covered-line-num-bg: #9ae6a4;--missed-bg: #ffd8d5;--missed-line-num-bg: #ffb8b3;--never-bg: #fff;--never-line-num-bg: #f0f1f3;--skipped-bg: #fff0a0;--skipped-line-num-bg: #eed860;--missed-branch-bg: #ffd0a0;--missed-branch-line-num-bg: #ffb060;--missed-branch-text: #b45309;--missed-method-bg: #e8d0ff;--missed-method-line-num-bg: #d4b0ff;--missed-method-text: #7b2d8e;--source-bg: #fff;--source-border: #c0c5cc;--source-line-number: #444;--source-line-num-bg: #f0f1f3;--hits-bg: #e0e3e8;--hits-color: #333;--overlay-bg: rgba(0, 0, 0, .5);--bar-bg: #d0d7de;--bar-height: 6px}@media(prefers-color-scheme:dark){:root:not(.light-mode){--bg: #010409;--surface: #0d1117;--surface-alt: #161b22;--text: #f0f3f6;--text-secondary: #b0b8c4;--text-tertiary: #9aa5b1;--zebra: #161b22;--border: #3d444d;--border-strong: #555e68;--accent: #6cb6ff;--accent-hover: #96ccff;--accent-subtle: #121d2f;--green: #56d364;--red: #ff6b61;--yellow: #e3b341;--orange: #f0883e;--covered-bg: #122d1e;--covered-line-num-bg: #1e4430;--missed-bg: #351418;--missed-line-num-bg: #4e1d20;--never-bg: #0d1117;--never-line-num-bg: #161b22;--skipped-bg: #302818;--skipped-line-num-bg: #443920;--missed-branch-bg: #322218;--missed-branch-line-num-bg: #483020;--missed-branch-text: #ffb86c;--missed-method-bg: #1e1830;--missed-method-line-num-bg: #2a2044;--missed-method-text: #dcb8ff;--source-bg: #0d1117;--source-border: #3d444d;--source-line-number: #9aa5b1;--source-line-num-bg: #161b22;--hits-bg: #262c34;--hits-color: #b0b8c4;--overlay-bg: rgba(1, 4, 9, .8);--bar-bg: #3d444d}}.dark-mode{--bg: #010409;--surface: #0d1117;--surface-alt: #161b22;--text: #f0f3f6;--text-secondary: #b0b8c4;--text-tertiary: #9aa5b1;--zebra: #161b22;--border: #3d444d;--border-strong: #555e68;--accent: #6cb6ff;--accent-hover: #96ccff;--accent-subtle: #121d2f;--green: #56d364;--red: #ff6b61;--yellow: #e3b341;--orange: #f0883e;--covered-bg: #122d1e;--covered-line-num-bg: #1e4430;--missed-bg: #351418;--missed-line-num-bg: #4e1d20;--never-bg: #0d1117;--never-line-num-bg: #161b22;--skipped-bg: #302818;--skipped-line-num-bg: #443920;--missed-branch-bg: #322218;--missed-branch-line-num-bg: #483020;--missed-branch-text: #ffb86c;--missed-method-bg: #1e1830;--missed-method-line-num-bg: #2a2044;--missed-method-text: #dcb8ff;--source-bg: #0d1117;--source-border: #3d444d;--source-line-number: #9aa5b1;--source-line-num-bg: #161b22;--hits-bg: #262c34;--hits-color: #b0b8c4;--overlay-bg: rgba(1, 4, 9, .8);--bar-bg: #3d444d}body{font-family:var(--font-sans);font-size:18px;color:var(--text);background:var(--bg);padding:var(--sp-6)}a{color:var(--accent);text-decoration:none;transition:color .15s}a:hover{color:var(--accent-hover)}strong,b{font-weight:600}#loading{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;background:var(--bg);z-index:9999}#loading-inner{width:280px;text-align:center}#loading-bar-track{width:100%;height:6px;background:var(--bar-bg);border-radius:6px;overflow:hidden}#loading-bar-fill{width:0%;height:100%;background:var(--accent);border-radius:6px;transition:width .15s ease-out}#loading-text{margin-top:var(--sp-3);font-size:18px;color:var(--text-tertiary)}#wrapper{margin:0 auto}.tab-bar{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--sp-4);margin-bottom:-1px;position:relative;z-index:1}abbr.timeago{text-decoration:none;border:none}.group_tabs{display:flex;align-self:flex-end;gap:var(--sp-1);overflow-x:auto}.group_tabs li a{display:block;padding:var(--sp-2) var(--sp-4);font-size:18px;font-weight:500;color:var(--text-secondary);background:transparent;border:1px solid transparent;border-bottom:none;border-radius:var(--radius-md) var(--radius-md) 0 0;white-space:nowrap;transition:color .15s,background .15s}.group_tabs li a:hover{color:var(--text);background:var(--surface-alt);text-decoration:none}.group_tabs li.active a{color:var(--accent);background:var(--surface);border-color:var(--border);font-weight:600}#content{background:var(--surface);border:1px solid var(--border);border-radius:0 var(--radius-lg) var(--radius-lg) var(--radius-lg);padding:var(--sp-6)}.file_list_container h2{font-size:24px;font-weight:600;color:var(--text);margin:0}.file_list_container h2 .covered_percent{font-weight:600}.summary-stats{display:flex;flex-direction:column;gap:var(--sp-1);font-size:18px;color:var(--text-secondary)}.summary-stats b{color:var(--text)}.summary-stats .missed-branch-text b,.summary-stats .missed-method-text-color b,.summary-stats .green b,.summary-stats .red b{color:inherit}.summary-stats .green{color:var(--green)}.summary-stats .red{color:var(--red)}.coverage-disabled{color:var(--text-tertiary);font-style:italic}.th-with-filter{display:flex;align-items:center;gap:var(--sp-2)}table.file_list th.cell--coverage .th-with-filter{white-space:nowrap;justify-content:flex-end}.th-with-filter .th-label{white-space:nowrap}.col-filter--name{width:100%;min-width:200px;border:1px solid var(--border);border-radius:999px;padding:var(--sp-1) var(--sp-4);font-size:14px;background:var(--surface);color:var(--text);outline:none}.col-filter--name:focus{border-color:var(--accent)}.col-filter__coverage{display:flex;gap:var(--sp-1)}.col-filter__op{border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--sp-1) var(--sp-1);font-size:14px;background:var(--surface);color:var(--text);cursor:pointer}.col-filter__value{border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--sp-1) var(--sp-2);font-size:14px;background:var(--surface);color:var(--text);width:60px;outline:none}.col-filter__value:focus{border-color:var(--accent)}.file_list--responsive{overflow-x:auto}table.file_list{width:100%;font-size:18px}table.file_list{border-collapse:separate;border-spacing:0}table.file_list thead th{font-size:14px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--text-tertiary);background:var(--surface);padding:var(--sp-2) var(--sp-2);border-bottom:2px solid var(--border-strong);white-space:nowrap}table.file_list tbody tr{background:var(--surface);cursor:pointer}table.file_list tbody tr:nth-child(2n){background:var(--zebra)}table.file_list tbody tr:hover{background:var(--accent-subtle)}table.file_list tbody tr.keyboard-focus{background:var(--accent-subtle);outline:2px solid var(--accent);outline-offset:-2px}table.file_list tbody td{padding:var(--sp-2) var(--sp-2);border-bottom:1px solid var(--border);color:var(--text)}table.file_list td.cell--number{text-align:right;font-variant-numeric:tabular-nums;color:var(--text)}table.file_list th.cell--left,table.file_list th.cell--coverage{text-align:left}table.file_list th.cell--number{text-align:right}table.file_list th.cell--numerator{text-align:right;padding-right:0}table.file_list th.cell--denominator{text-align:left;padding-left:0}table.file_list td.strong{font-weight:600;color:var(--text)}table.file_list td.t-file__name{white-space:nowrap}a.src_link{color:var(--accent);font-weight:500;word-break:break-all}table.file_list td.cell--coverage{white-space:nowrap}.coverage-cell{display:flex;flex-wrap:nowrap;align-items:center;justify-content:flex-end;gap:10px}.coverage-cell .coverage-pct{flex:0 0 4.5em;font-variant-numeric:tabular-nums}.coverage-cell .bar-sizer{flex:0 0 auto;width:240px;min-width:160px;max-width:240px}table.file_list td.cell--numerator{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap;padding-left:var(--sp-1);padding-right:0}table.file_list td.cell--denominator{text-align:left;font-variant-numeric:tabular-nums;white-space:nowrap;padding-left:0;padding-right:var(--sp-1)}table.file_list .totals-row td.cell--numerator{color:var(--text);padding-right:0}table.file_list .totals-row td.cell--denominator{color:var(--text);padding-left:0}.coverage-cell__fraction{font-variant-numeric:tabular-nums;color:var(--text-secondary);font-size:14px;white-space:nowrap}.coverage-bar{width:100%;height:var(--bar-height);background:var(--bar-bg);border-radius:6px;overflow:hidden}.coverage-bar__fill{height:100%;border-radius:6px}.coverage-bar__fill--green{background:var(--green)}.coverage-bar__fill--yellow{background:var(--yellow)}.coverage-bar__fill--red{background:var(--red)}.green,table.file_list td.green{color:var(--green)}.red,table.file_list td.red{color:var(--red)}.yellow,table.file_list td.yellow{color:var(--yellow)}.missed-branch-text{color:var(--missed-branch-text)}.missed-method-text-color{color:var(--missed-method-text)}dialog.source-dialog{position:fixed;inset:0;width:100%;height:100%;max-width:100%;max-height:100%;border:none;padding:0;background:var(--bg);color:var(--text);overflow:hidden}dialog.source-dialog::backdrop{background:var(--overlay-bg)}dialog.source-dialog[open]{display:flex;flex-direction:column}.source-dialog__header{display:flex;align-items:flex-start;justify-content:space-between;padding:var(--sp-4) var(--sp-6);background:var(--surface);border-bottom:1px solid var(--border);flex-shrink:0}.source-dialog__title{flex:1;min-width:0}.source-dialog__title h2{font-size:22px;font-weight:700;color:var(--text);margin-bottom:var(--sp-2);word-break:break-all}.source-legend{display:flex;flex-wrap:wrap;gap:var(--sp-2) var(--sp-4);align-items:center;align-self:flex-end;flex-shrink:0;margin-left:auto;padding-left:var(--sp-6)}.source-legend__item{display:flex;align-items:center;gap:var(--sp-1);font-size:13px;color:var(--text-secondary);white-space:nowrap}.source-legend__swatch{display:inline-block;width:14px;height:14px;border-radius:3px;border:1px solid var(--border)}.source-legend__swatch--covered{background:var(--covered-bg);border-color:var(--covered-line-num-bg)}.source-legend__swatch--missed{background:var(--missed-bg);border-color:var(--missed-line-num-bg)}.source-legend__swatch--skipped{background:var(--skipped-bg);border-color:var(--skipped-line-num-bg)}.source-legend__swatch--missed-branch{background:var(--missed-branch-bg);border-color:var(--missed-branch-line-num-bg)}.source-legend__swatch--missed-method{background:var(--missed-method-bg);border-color:var(--missed-method-line-num-bg)}.source-dialog__close{appearance:none;background:none;border:1px solid var(--border);border-radius:50%;width:34px;height:34px;font-size:0;color:var(--text-secondary);cursor:pointer;position:relative;flex-shrink:0;margin-left:var(--sp-4);transition:color .15s,border-color .15s}.source-dialog__close:before,.source-dialog__close:after{content:"";position:absolute;top:50%;left:50%;width:14px;height:2px;background:currentColor;border-radius:1px}.source-dialog__close:before{transform:translate(-50%,-50%) rotate(45deg)}.source-dialog__close:after{transform:translate(-50%,-50%) rotate(-45deg)}.source-dialog__close:hover{color:var(--text);border-color:var(--border-strong)}.source-dialog__body{flex:1;overflow:auto}.source_table .header{padding:var(--sp-4) var(--sp-6);background:var(--surface)}.source_table .header h2{font-size:22px;font-weight:700;color:var(--text);margin-bottom:var(--sp-2)}table.file_list .totals-row td{padding:var(--sp-2) var(--sp-2);font-weight:600;border-bottom:2px solid var(--border-strong);background:var(--surface-alt)}.totals-row .t-file-count{font-size:18px;font-weight:700;color:var(--text)}.t-missed-method-toggle{color:var(--missed-method-text);font-weight:600;cursor:pointer;text-decoration:none}.t-missed-method-toggle:hover{text-decoration:underline;color:var(--missed-method-text)}.t-missed-method-list ul{padding-left:2em;margin-top:var(--sp-1);max-height:200px;overflow-y:auto}.t-missed-method-list li{list-style:none}.source_table pre{margin:0;padding:0;white-space:normal;color:var(--text);font-family:var(--font-mono);font-size:16px;line-height:24px;background:var(--source-bg);border:1px solid var(--source-border);border-top:none}.source_table code{color:inherit;font-family:var(--font-mono)}.source_table pre ol{margin:0;padding:0;list-style:none;counter-reset:linenumber}.source_table pre li{display:flex;counter-increment:linenumber;background:var(--never-bg)}.source_table pre li:before{content:counter(linenumber);flex-shrink:0;width:50px;padding:0 8px;text-align:right;color:var(--source-line-number);background:var(--source-line-num-bg);border-right:1px solid var(--source-border);-webkit-user-select:none;user-select:none;cursor:pointer}.source_table pre li:hover:before{color:var(--text)}.source_table pre li:hover{cursor:pointer}.source_table pre li code{order:1;flex:1;min-width:0;padding:0 12px;white-space:pre-wrap}.source_table pre .hits{order:2;flex-shrink:0;padding:0 var(--sp-2);background:var(--hits-bg);color:var(--hits-color);font-family:var(--font-mono);font-size:14px;text-align:center;line-height:24px;border-left:1px solid var(--source-border);-webkit-user-select:none;user-select:none}.source_table pre .hits:after{content:attr(data-content)}.source_table .covered{background-color:var(--covered-bg)}.source_table .missed{background-color:var(--missed-bg)}.source_table .never{background-color:var(--never-bg)}.source_table .skipped{background-color:var(--skipped-bg)}.source_table .missed-branch{background-color:var(--missed-branch-bg)}.source_table .missed-method{background-color:var(--missed-method-bg)}.source_table .covered:before{background-color:var(--covered-line-num-bg)}.source_table .missed:before{background-color:var(--missed-line-num-bg)}.source_table .never:before{background-color:var(--never-line-num-bg)}.source_table .skipped:before{background-color:var(--skipped-line-num-bg)}.source_table .missed-branch:before{background-color:var(--missed-branch-line-num-bg)}.source_table .missed-method:before{background-color:var(--missed-method-line-num-bg)}#dark-mode-toggle{appearance:none;background:var(--surface);color:var(--text-secondary);border:1px solid var(--border);border-radius:999px;padding:var(--sp-1) var(--sp-4);font-size:16px;font-family:var(--font-sans);cursor:pointer;white-space:nowrap;transition:color .15s,border-color .15s}#dark-mode-toggle:hover{color:var(--text);border-color:var(--border-strong)}#footer{color:var(--text-tertiary);font-size:16px;margin-top:var(--sp-5);text-align:center}#footer a{color:var(--text-secondary);text-decoration:underline}#footer a:hover{color:var(--text)}table.file_list thead th.sorting,table.file_list thead th.sorting_asc,table.file_list thead th.sorting_desc{cursor:pointer;position:relative;padding-right:12px}table.file_list thead th.sorting:after,table.file_list thead th.sorting_asc:after,table.file_list thead th.sorting_desc:after{position:absolute;right:2px;top:50%;transform:translateY(-50%);font-size:14px;color:var(--text-tertiary)}table.file_list thead th.sorting:after{content:"\2195"}table.file_list thead th.sorting_asc:after{content:"\2191"}table.file_list thead th.sorting_desc:after{content:"\2193"}@media print{:root,.dark-mode{--bg: #fff;--surface: #fff;--surface-alt: #f4f5f7;--text: #111;--text-secondary: #333;--text-tertiary: #444;--zebra: #f4f5f7;--border: #c0c5cc;--border-strong: #999;--accent: #0550ae;--green: #116329;--red: #a40e26;--yellow: #7a5200;--orange: #953800;--bar-bg: #d0d7de;--covered-bg: #ccf5d0;--covered-line-num-bg: #9ae6a4;--missed-bg: #ffd8d5;--missed-line-num-bg: #ffb8b3;--never-bg: #fff;--never-line-num-bg: #f0f1f3;--skipped-bg: #fff0a0;--skipped-line-num-bg: #eed860;--missed-branch-bg: #ffd0a0;--missed-branch-line-num-bg: #ffb060;--missed-branch-text: #b45309;--missed-method-bg: #e8d0ff;--missed-method-line-num-bg: #d4b0ff;--missed-method-text: #7b2d8e;--source-bg: #fff;--source-border: #c0c5cc;--source-line-number: #444;--source-line-num-bg: #f0f1f3;--hits-bg: #e0e3e8;--hits-color: #333}body{padding:0;font-size:12pt}#loading,#dark-mode-toggle,.tab-bar,.source_files,.col-filter--name,.col-filter__coverage,table.file_list thead th.sorting:after,table.file_list thead th.sorting_asc:after,table.file_list thead th.sorting_desc:after{display:none!important}#wrapper,.file_list_container{display:block!important}body:has(.source-dialog[open]) #wrapper{display:none!important}#content{border:none;border-radius:0;padding:0}.file_list_container .group_name{display:inline!important;font-size:16pt;font-weight:700}.file_list_container .covered_percent{display:inline!important;font-weight:600}.file_list_container+.file_list_container{margin-top:24pt}dialog.source-dialog{display:none}dialog.source-dialog[open]{display:block!important;position:static;width:100%;height:auto;max-height:none;overflow:visible;background:#fff}.source-dialog__close{display:none!important}.source-dialog__header{flex-wrap:wrap;border-bottom:none;padding:0 0 8pt}.source-dialog__title{flex:0 0 100%}.source-dialog__title h2{word-break:normal;overflow-wrap:break-word}.source-legend{margin-left:0;padding-left:0;padding-top:var(--sp-2)}.source-dialog__body{overflow:visible}.source_table pre{font-size:8pt;line-height:1.4}.source_table pre li{-webkit-print-color-adjust:exact;print-color-adjust:exact}.source_table pre li:before{-webkit-print-color-adjust:exact;print-color-adjust:exact}.source_table pre .hits{-webkit-print-color-adjust:exact;print-color-adjust:exact}.coverage-bar{border:1px solid var(--border);-webkit-print-color-adjust:exact;print-color-adjust:exact}.coverage-bar__fill{-webkit-print-color-adjust:exact;print-color-adjust:exact}table.file_list tbody tr:nth-child(2n){-webkit-print-color-adjust:exact;print-color-adjust:exact}table.file_list{font-size:10pt}table.file_list thead th{font-size:9pt}table.file_list{page-break-inside:auto}table.file_list tr{page-break-inside:avoid}table.file_list thead{display:table-header-group}#footer{font-size:10pt;margin-top:12pt}#footer a:after{content:" (" attr(href) ")";font-size:9pt;color:var(--text-tertiary)}}
|
|
1
|
+
*,*:before,*:after{box-sizing:border-box}*{margin:0;padding:0}html{-moz-text-size-adjust:none;-webkit-text-size-adjust:none;text-size-adjust:none}body{min-height:100vh;line-height:1.5;-webkit-font-smoothing:antialiased}img,picture,svg{display:block;max-width:100%}input,button,textarea,select{font:inherit}h1,h2,h3,h4,h5,h6{overflow-wrap:break-word;text-wrap:balance}p{overflow-wrap:break-word;text-wrap:pretty}table{border-collapse:collapse;border-spacing:0}ul,ol{list-style:none}a{text-decoration-skip-ink:auto;color:currentColor}.hide{display:none}.hljs{color:#24292e}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#005cc5}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-comment,.hljs-code,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}@media(prefers-color-scheme:dark){:root:not(.light-mode) .hljs{color:#c9d1d9}:root:not(.light-mode) .hljs-doctag,:root:not(.light-mode) .hljs-keyword,:root:not(.light-mode) .hljs-meta .hljs-keyword,:root:not(.light-mode) .hljs-template-tag,:root:not(.light-mode) .hljs-template-variable,:root:not(.light-mode) .hljs-type,:root:not(.light-mode) .hljs-variable.language_{color:#ff7b72}:root:not(.light-mode) .hljs-title,:root:not(.light-mode) .hljs-title.class_,:root:not(.light-mode) .hljs-title.class_.inherited__,:root:not(.light-mode) .hljs-title.function_{color:#d2a8ff}:root:not(.light-mode) .hljs-attr,:root:not(.light-mode) .hljs-attribute,:root:not(.light-mode) .hljs-literal,:root:not(.light-mode) .hljs-meta,:root:not(.light-mode) .hljs-number,:root:not(.light-mode) .hljs-operator,:root:not(.light-mode) .hljs-variable,:root:not(.light-mode) .hljs-selector-attr,:root:not(.light-mode) .hljs-selector-class,:root:not(.light-mode) .hljs-selector-id{color:#79c0ff}:root:not(.light-mode) .hljs-regexp,:root:not(.light-mode) .hljs-string,:root:not(.light-mode) .hljs-meta .hljs-string{color:#a5d6ff}:root:not(.light-mode) .hljs-built_in,:root:not(.light-mode) .hljs-symbol{color:#ffa657}:root:not(.light-mode) .hljs-comment,:root:not(.light-mode) .hljs-code,:root:not(.light-mode) .hljs-formula{color:#8b949e}:root:not(.light-mode) .hljs-name,:root:not(.light-mode) .hljs-quote,:root:not(.light-mode) .hljs-selector-tag,:root:not(.light-mode) .hljs-selector-pseudo{color:#7ee787}:root:not(.light-mode) .hljs-subst{color:#c9d1d9}:root:not(.light-mode) .hljs-section{color:#1f6feb}}.dark-mode .hljs{color:#c9d1d9}.dark-mode .hljs-doctag,.dark-mode .hljs-keyword,.dark-mode .hljs-meta .hljs-keyword,.dark-mode .hljs-template-tag,.dark-mode .hljs-template-variable,.dark-mode .hljs-type,.dark-mode .hljs-variable.language_{color:#ff7b72}.dark-mode .hljs-title,.dark-mode .hljs-title.class_,.dark-mode .hljs-title.class_.inherited__,.dark-mode .hljs-title.function_{color:#d2a8ff}.dark-mode .hljs-attr,.dark-mode .hljs-attribute,.dark-mode .hljs-literal,.dark-mode .hljs-meta,.dark-mode .hljs-number,.dark-mode .hljs-operator,.dark-mode .hljs-variable,.dark-mode .hljs-selector-attr,.dark-mode .hljs-selector-class,.dark-mode .hljs-selector-id{color:#79c0ff}.dark-mode .hljs-regexp,.dark-mode .hljs-string,.dark-mode .hljs-meta .hljs-string{color:#a5d6ff}.dark-mode .hljs-built_in,.dark-mode .hljs-symbol{color:#ffa657}.dark-mode .hljs-comment,.dark-mode .hljs-code,.dark-mode .hljs-formula{color:#8b949e}.dark-mode .hljs-name,.dark-mode .hljs-quote,.dark-mode .hljs-selector-tag,.dark-mode .hljs-selector-pseudo{color:#7ee787}.dark-mode .hljs-subst{color:#c9d1d9}.dark-mode .hljs-section{color:#1f6feb}:root{--font-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--font-mono: ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, Consolas, "DejaVu Sans Mono", monospace;--sp-1: 4px;--sp-2: 8px;--sp-3: 12px;--sp-4: 16px;--sp-5: 20px;--sp-6: 24px;--sp-8: 32px;--radius-sm: 8px;--radius-md: 12px;--radius-lg: 16px;--bg: #f0f1f3;--surface: #fff;--surface-alt: #f0f1f3;--text: #111;--text-secondary: #333;--text-tertiary: #444;--zebra: #f4f5f7;--border: #c0c5cc;--border-strong: #999;--accent: #0550ae;--accent-hover: #033d8b;--accent-subtle: #ddf4ff;--green: #116329;--red: #a40e26;--yellow: #7a5200;--orange: #953800;--covered-bg: #ccf5d0;--covered-line-num-bg: #9ae6a4;--missed-bg: #ffd8d5;--missed-line-num-bg: #ffb8b3;--never-bg: #fff;--never-line-num-bg: #f0f1f3;--skipped-bg: #fff0a0;--skipped-line-num-bg: #eed860;--missed-branch-bg: #ffd0a0;--missed-branch-line-num-bg: #ffb060;--missed-branch-text: #b45309;--missed-method-bg: #e8d0ff;--missed-method-line-num-bg: #d4b0ff;--missed-method-text: #7b2d8e;--source-bg: #fff;--source-border: #c0c5cc;--source-line-number: #444;--source-line-num-bg: #f0f1f3;--hits-bg: #e0e3e8;--hits-color: #333;--overlay-bg: rgba(0, 0, 0, .5);--bar-bg: #d0d7de;--bar-height: 6px}@media(prefers-color-scheme:dark){:root:not(.light-mode){--bg: #010409;--surface: #0d1117;--surface-alt: #161b22;--text: #f0f3f6;--text-secondary: #b0b8c4;--text-tertiary: #9aa5b1;--zebra: #161b22;--border: #3d444d;--border-strong: #555e68;--accent: #6cb6ff;--accent-hover: #96ccff;--accent-subtle: #121d2f;--green: #56d364;--red: #ff6b61;--yellow: #e3b341;--orange: #f0883e;--covered-bg: #122d1e;--covered-line-num-bg: #1e4430;--missed-bg: #351418;--missed-line-num-bg: #4e1d20;--never-bg: #0d1117;--never-line-num-bg: #161b22;--skipped-bg: #302818;--skipped-line-num-bg: #443920;--missed-branch-bg: #322218;--missed-branch-line-num-bg: #483020;--missed-branch-text: #ffb86c;--missed-method-bg: #1e1830;--missed-method-line-num-bg: #2a2044;--missed-method-text: #dcb8ff;--source-bg: #0d1117;--source-border: #3d444d;--source-line-number: #9aa5b1;--source-line-num-bg: #161b22;--hits-bg: #262c34;--hits-color: #b0b8c4;--overlay-bg: rgba(1, 4, 9, .8);--bar-bg: #3d444d}}.dark-mode{--bg: #010409;--surface: #0d1117;--surface-alt: #161b22;--text: #f0f3f6;--text-secondary: #b0b8c4;--text-tertiary: #9aa5b1;--zebra: #161b22;--border: #3d444d;--border-strong: #555e68;--accent: #6cb6ff;--accent-hover: #96ccff;--accent-subtle: #121d2f;--green: #56d364;--red: #ff6b61;--yellow: #e3b341;--orange: #f0883e;--covered-bg: #122d1e;--covered-line-num-bg: #1e4430;--missed-bg: #351418;--missed-line-num-bg: #4e1d20;--never-bg: #0d1117;--never-line-num-bg: #161b22;--skipped-bg: #302818;--skipped-line-num-bg: #443920;--missed-branch-bg: #322218;--missed-branch-line-num-bg: #483020;--missed-branch-text: #ffb86c;--missed-method-bg: #1e1830;--missed-method-line-num-bg: #2a2044;--missed-method-text: #dcb8ff;--source-bg: #0d1117;--source-border: #3d444d;--source-line-number: #9aa5b1;--source-line-num-bg: #161b22;--hits-bg: #262c34;--hits-color: #b0b8c4;--overlay-bg: rgba(1, 4, 9, .8);--bar-bg: #3d444d}body{font-family:var(--font-sans);font-size:18px;color:var(--text);background:var(--bg);padding:var(--sp-6)}a{color:var(--accent);text-decoration:none;transition:color .15s}a:hover{color:var(--accent-hover)}strong,b{font-weight:600}#loading{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;background:var(--bg);z-index:9999}#loading-inner{width:280px;text-align:center}#loading-bar-track{width:100%;height:6px;background:var(--bar-bg);border-radius:6px;overflow:hidden}#loading-bar-fill{width:0%;height:100%;background:var(--accent);border-radius:6px;transition:width .15s ease-out}#loading-text{margin-top:var(--sp-3);font-size:18px;color:var(--text-tertiary)}#sort-overlay{position:fixed;inset:0;z-index:9998;display:flex;align-items:center;justify-content:center;background:var(--overlay-bg)}#sort-overlay-label{padding:var(--sp-2) var(--sp-4);border:1px solid var(--border);border-radius:6px;background:var(--bg);font-size:16px;color:var(--text-tertiary)}#wrapper{margin:0 auto}.tab-bar{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--sp-4);margin-bottom:-1px;position:relative;z-index:1}abbr.timeago{text-decoration:none;border:none}.group_tabs{display:flex;align-self:flex-end;gap:var(--sp-1);overflow-x:auto}.group_tabs li a{display:block;padding:var(--sp-2) var(--sp-4);font-size:18px;font-weight:500;color:var(--text-secondary);background:transparent;border:1px solid transparent;border-bottom:none;border-radius:var(--radius-md) var(--radius-md) 0 0;white-space:nowrap;transition:color .15s,background .15s}.group_tabs li a:hover{color:var(--text);background:var(--surface-alt);text-decoration:none}.group_tabs li.active a{color:var(--accent);background:var(--surface);border-color:var(--border);font-weight:600}#content{background:var(--surface);border:1px solid var(--border);border-radius:0 var(--radius-lg) var(--radius-lg) var(--radius-lg);padding:var(--sp-6)}.file_list_container h2{font-size:24px;font-weight:600;color:var(--text);margin:0}.file_list_container h2 .covered_percent{font-weight:600}.summary-stats{display:flex;flex-direction:column;gap:var(--sp-1);font-size:18px;color:var(--text-secondary)}.summary-stats b{color:var(--text)}.summary-stats .missed-branch-text b,.summary-stats .missed-method-text-color b,.summary-stats .green b,.summary-stats .red b{color:inherit}.summary-stats .green{color:var(--green)}.summary-stats .red{color:var(--red)}.coverage-disabled{color:var(--text-tertiary);font-style:italic}.th-with-filter{display:flex;align-items:center;gap:var(--sp-2)}table.file_list th.cell--coverage .th-with-filter{white-space:nowrap;justify-content:flex-end}.th-with-filter .th-label{white-space:nowrap}.col-filter--name{width:100%;min-width:200px;border:1px solid var(--border);border-radius:999px;padding:var(--sp-1) var(--sp-4);font-size:14px;background:var(--surface);color:var(--text);outline:none}.col-filter--name:focus{border-color:var(--accent)}.col-filter__coverage{display:flex;gap:var(--sp-1)}.col-filter__op{border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--sp-1) var(--sp-1);font-size:14px;background:var(--surface);color:var(--text);cursor:pointer}.col-filter__value{border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--sp-1) var(--sp-2);font-size:14px;background:var(--surface);color:var(--text);width:60px;outline:none}.col-filter__value:focus{border-color:var(--accent)}.file_list--responsive{overflow-x:auto}table.file_list{width:100%;font-size:18px}table.file_list{border-collapse:separate;border-spacing:0}table.file_list thead th{font-size:14px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--text-tertiary);background:var(--surface);padding:var(--sp-2) var(--sp-2);border-bottom:2px solid var(--border-strong);white-space:nowrap}table.file_list tbody tr{background:var(--surface);cursor:pointer}table.file_list tbody tr:nth-child(2n){background:var(--zebra)}table.file_list tbody tr:hover{background:var(--accent-subtle)}table.file_list tbody tr.keyboard-focus{background:var(--accent-subtle);outline:2px solid var(--accent);outline-offset:-2px}table.file_list tbody td{padding:var(--sp-2) var(--sp-2);border-bottom:1px solid var(--border);color:var(--text)}table.file_list td.cell--number{text-align:right;font-variant-numeric:tabular-nums;color:var(--text)}table.file_list th.cell--left,table.file_list th.cell--coverage{text-align:left}table.file_list th.cell--number{text-align:right}table.file_list th.cell--numerator{text-align:right;padding-right:0}table.file_list th.cell--denominator{text-align:left;padding-left:0}table.file_list td.strong{font-weight:600;color:var(--text)}table.file_list td.t-file__name{white-space:nowrap}a.src_link{color:var(--accent);font-weight:500;word-break:break-all}table.file_list td.cell--coverage{white-space:nowrap}.coverage-cell{display:flex;flex-wrap:nowrap;align-items:center;justify-content:flex-end;gap:10px}.coverage-cell .coverage-pct{flex:0 0 4.5em;font-variant-numeric:tabular-nums}tr.t-window-hidden{display:none}tr.t-show-all td{padding:var(--sp-3);text-align:center;color:var(--text-tertiary);cursor:pointer}.coverage-cell .bar-sizer{flex:0 0 auto;width:var(--bar-sizer-width, 240px);min-width:160px;max-width:240px}table.file_list td.cell--numerator{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap;padding-left:var(--sp-1);padding-right:0}table.file_list td.cell--denominator{text-align:left;font-variant-numeric:tabular-nums;white-space:nowrap;padding-left:0;padding-right:var(--sp-1)}table.file_list .totals-row td.cell--numerator{color:var(--text);padding-right:0}table.file_list .totals-row td.cell--denominator{color:var(--text);padding-left:0}.coverage-cell__fraction{font-variant-numeric:tabular-nums;color:var(--text-secondary);font-size:14px;white-space:nowrap}.coverage-bar{width:100%;height:var(--bar-height);background:var(--bar-bg);border-radius:6px;overflow:hidden}.coverage-bar__fill{height:100%;border-radius:6px}.coverage-bar__fill--green{background:var(--green)}.coverage-bar__fill--yellow{background:var(--yellow)}.coverage-bar__fill--red{background:var(--red)}.green,table.file_list td.green{color:var(--green)}.red,table.file_list td.red{color:var(--red)}.yellow,table.file_list td.yellow{color:var(--yellow)}.missed-branch-text{color:var(--missed-branch-text)}.missed-method-text-color{color:var(--missed-method-text)}dialog.source-dialog{position:fixed;inset:0;width:100%;height:100%;max-width:100%;max-height:100%;border:none;padding:0;background:var(--bg);color:var(--text);overflow:hidden}dialog.source-dialog::backdrop{background:var(--overlay-bg)}dialog.source-dialog[open]{display:flex;flex-direction:column}.source-dialog__header{display:flex;align-items:flex-start;justify-content:space-between;padding:var(--sp-4) var(--sp-6);background:var(--surface);border-bottom:1px solid var(--border);flex-shrink:0}.source-dialog__title{flex:1;min-width:0}.source-dialog__title h2{font-size:22px;font-weight:700;color:var(--text);margin-bottom:var(--sp-2);word-break:break-all}.source-legend{display:flex;flex-wrap:wrap;gap:var(--sp-2) var(--sp-4);align-items:center;align-self:flex-end;flex-shrink:0;margin-left:auto;padding-left:var(--sp-6)}.source-legend__item{display:flex;align-items:center;gap:var(--sp-1);font-size:13px;color:var(--text-secondary);white-space:nowrap}.source-legend__swatch{display:inline-block;width:14px;height:14px;border-radius:3px;border:1px solid var(--border)}.source-legend__swatch--covered{background:var(--covered-bg);border-color:var(--covered-line-num-bg)}.source-legend__swatch--missed{background:var(--missed-bg);border-color:var(--missed-line-num-bg)}.source-legend__swatch--skipped{background:var(--skipped-bg);border-color:var(--skipped-line-num-bg)}.source-legend__swatch--missed-branch{background:var(--missed-branch-bg);border-color:var(--missed-branch-line-num-bg)}.source-legend__swatch--missed-method{background:var(--missed-method-bg);border-color:var(--missed-method-line-num-bg)}.source-dialog__close{appearance:none;background:none;border:1px solid var(--border);border-radius:50%;width:34px;height:34px;font-size:0;color:var(--text-secondary);cursor:pointer;position:relative;flex-shrink:0;margin-left:var(--sp-4);transition:color .15s,border-color .15s}.source-dialog__close:before,.source-dialog__close:after{content:"";position:absolute;top:50%;left:50%;width:14px;height:2px;background:currentColor;border-radius:1px}.source-dialog__close:before{transform:translate(-50%,-50%) rotate(45deg)}.source-dialog__close:after{transform:translate(-50%,-50%) rotate(-45deg)}.source-dialog__close:hover{color:var(--text);border-color:var(--border-strong)}.source-dialog__body{flex:1;overflow:auto}.source_table .header{padding:var(--sp-4) var(--sp-6);background:var(--surface)}.source_table .header h2{font-size:22px;font-weight:700;color:var(--text);margin-bottom:var(--sp-2)}table.file_list .totals-row td{padding:var(--sp-2) var(--sp-2);font-weight:600;border-bottom:2px solid var(--border-strong);background:var(--surface-alt)}.totals-row .t-file-count{font-size:18px;font-weight:700;color:var(--text)}.t-missed-method-toggle{color:var(--missed-method-text);font-weight:600;cursor:pointer;text-decoration:none}.t-missed-method-toggle:hover{text-decoration:underline;color:var(--missed-method-text)}.t-missed-method-list ul{padding-left:2em;margin-top:var(--sp-1);max-height:200px;overflow-y:auto}.t-missed-method-list li{list-style:none}.source_table pre{margin:0;padding:0;white-space:normal;color:var(--text);font-family:var(--font-mono);font-size:16px;line-height:24px;background:var(--source-bg);border:1px solid var(--source-border);border-top:none}.source_table code{color:inherit;font-family:var(--font-mono)}.source_table pre ol{margin:0;padding:0;list-style:none;counter-reset:linenumber}.source_table pre li{display:flex;counter-increment:linenumber;background:var(--never-bg)}.source_table pre li:before{content:counter(linenumber);flex-shrink:0;width:50px;padding:0 8px;text-align:right;color:var(--source-line-number);background:var(--source-line-num-bg);border-right:1px solid var(--source-border);-webkit-user-select:none;user-select:none;cursor:pointer}.source_table pre li:hover:before{color:var(--text)}.source_table pre li:hover{cursor:pointer}.source_table pre li code{order:1;flex:1;min-width:0;padding:0 12px;white-space:pre-wrap}.source_table pre .hits{order:2;flex-shrink:0;padding:0 var(--sp-2);background:var(--hits-bg);color:var(--hits-color);font-family:var(--font-mono);font-size:14px;text-align:center;line-height:24px;border-left:1px solid var(--source-border);-webkit-user-select:none;user-select:none}.source_table pre .hits:after{content:attr(data-content)}.source_table .covered{background-color:var(--covered-bg)}.source_table .missed{background-color:var(--missed-bg)}.source_table .never{background-color:var(--never-bg)}.source_table .skipped{background-color:var(--skipped-bg)}.source_table .missed-branch{background-color:var(--missed-branch-bg)}.source_table .missed-method{background-color:var(--missed-method-bg)}.source_table .covered:before{background-color:var(--covered-line-num-bg)}.source_table .missed:before{background-color:var(--missed-line-num-bg)}.source_table .never:before{background-color:var(--never-line-num-bg)}.source_table .skipped:before{background-color:var(--skipped-line-num-bg)}.source_table .missed-branch:before{background-color:var(--missed-branch-line-num-bg)}.source_table .missed-method:before{background-color:var(--missed-method-line-num-bg)}#dark-mode-toggle{appearance:none;background:var(--surface);color:var(--text-secondary);border:1px solid var(--border);border-radius:999px;padding:var(--sp-1) var(--sp-4);font-size:16px;font-family:var(--font-sans);cursor:pointer;white-space:nowrap;transition:color .15s,border-color .15s}#dark-mode-toggle:hover{color:var(--text);border-color:var(--border-strong)}#footer{color:var(--text-tertiary);font-size:16px;margin-top:var(--sp-5);text-align:center}#footer a{color:var(--text-secondary);text-decoration:underline}#footer a:hover{color:var(--text)}table.file_list thead th.sorting,table.file_list thead th.sorting_asc,table.file_list thead th.sorting_desc{cursor:pointer;position:relative;padding-right:12px}table.file_list thead th.sorting:after,table.file_list thead th.sorting_asc:after,table.file_list thead th.sorting_desc:after{position:absolute;right:2px;top:50%;transform:translateY(-50%);font-size:14px;color:var(--text-tertiary)}table.file_list thead th.sorting:after{content:"\2195"}table.file_list thead th.sorting_asc:after{content:"\2191"}table.file_list thead th.sorting_desc:after{content:"\2193"}@media print{:root,.dark-mode{--bg: #fff;--surface: #fff;--surface-alt: #f4f5f7;--text: #111;--text-secondary: #333;--text-tertiary: #444;--zebra: #f4f5f7;--border: #c0c5cc;--border-strong: #999;--accent: #0550ae;--green: #116329;--red: #a40e26;--yellow: #7a5200;--orange: #953800;--bar-bg: #d0d7de;--covered-bg: #ccf5d0;--covered-line-num-bg: #9ae6a4;--missed-bg: #ffd8d5;--missed-line-num-bg: #ffb8b3;--never-bg: #fff;--never-line-num-bg: #f0f1f3;--skipped-bg: #fff0a0;--skipped-line-num-bg: #eed860;--missed-branch-bg: #ffd0a0;--missed-branch-line-num-bg: #ffb060;--missed-branch-text: #b45309;--missed-method-bg: #e8d0ff;--missed-method-line-num-bg: #d4b0ff;--missed-method-text: #7b2d8e;--source-bg: #fff;--source-border: #c0c5cc;--source-line-number: #444;--source-line-num-bg: #f0f1f3;--hits-bg: #e0e3e8;--hits-color: #333}body{padding:0;font-size:12pt}#loading,#sort-overlay,#dark-mode-toggle,.tab-bar,.source_files,.col-filter--name,.col-filter__coverage,tr.t-show-all,table.file_list thead th.sorting:after,table.file_list thead th.sorting_asc:after,table.file_list thead th.sorting_desc:after{display:none!important}#wrapper,.file_list_container{display:block!important}body:has(.source-dialog[open]) #wrapper{display:none!important}#content{border:none;border-radius:0;padding:0}.file_list_container .group_name{display:inline!important;font-size:16pt;font-weight:700}.file_list_container .covered_percent{display:inline!important;font-weight:600}.file_list_container+.file_list_container{margin-top:24pt}dialog.source-dialog{display:none}dialog.source-dialog[open]{display:block!important;position:static;width:100%;height:auto;max-height:none;overflow:visible;background:#fff}.source-dialog__close{display:none!important}.source-dialog__header{flex-wrap:wrap;border-bottom:none;padding:0 0 8pt}.source-dialog__title{flex:0 0 100%}.source-dialog__title h2{word-break:normal;overflow-wrap:break-word}.source-legend{margin-left:0;padding-left:0;padding-top:var(--sp-2)}.source-dialog__body{overflow:visible}.source_table pre{font-size:8pt;line-height:1.4}.source_table pre li{-webkit-print-color-adjust:exact;print-color-adjust:exact}.source_table pre li:before{-webkit-print-color-adjust:exact;print-color-adjust:exact}.source_table pre .hits{-webkit-print-color-adjust:exact;print-color-adjust:exact}.coverage-bar{border:1px solid var(--border);-webkit-print-color-adjust:exact;print-color-adjust:exact}.coverage-bar__fill{-webkit-print-color-adjust:exact;print-color-adjust:exact}table.file_list tbody tr:nth-child(2n){-webkit-print-color-adjust:exact;print-color-adjust:exact}table.file_list{font-size:10pt}table.file_list thead th{font-size:9pt}table.file_list{page-break-inside:auto}table.file_list tr{page-break-inside:avoid}table.file_list thead{display:table-header-group}#footer{font-size:10pt;margin-top:12pt}#footer a:after{content:" (" attr(href) ")";font-size:9pt;color:var(--text-tertiary)}}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"use strict";(()=>{var hn=Object.create;var ct=Object.defineProperty;var mn=Object.getOwnPropertyDescriptor;var bn=Object.getOwnPropertyNames;var _n=Object.getPrototypeOf,En=Object.prototype.hasOwnProperty;var vn=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var yn=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of bn(t))!En.call(e,i)&&i!==n&&ct(e,i,{get:()=>t[i],enumerable:!(s=mn(t,i))||s.enumerable});return e};var Mn=(e,t,n)=>(n=e!=null?hn(_n(e)):{},yn(t||!e||!e.__esModule?ct(n,"default",{value:e,enumerable:!0}):n,e));var J=(e,t,n)=>new Promise((s,i)=>{var c=l=>{try{o(n.next(l))}catch(d){i(d)}},r=l=>{try{o(n.throw(l))}catch(d){i(d)}},o=l=>l.done?s(l.value):Promise.resolve(l.value).then(c,r);o((n=n.apply(e,t)).next())});var $t=vn((Zs,It)=>{function yt(e){return e instanceof Map?e.clear=e.delete=e.set=function(){throw new Error("map is read-only")}:e instanceof Set&&(e.add=e.clear=e.delete=function(){throw new Error("set is read-only")}),Object.freeze(e),Object.getOwnPropertyNames(e).forEach(t=>{let n=e[t],s=typeof n;(s==="object"||s==="function")&&!Object.isFrozen(n)&&yt(n)}),e}var Ee=class{constructor(t){t.data===void 0&&(t.data={}),this.data=t.data,this.isMatchIgnored=!1}ignoreMatch(){this.isMatchIgnored=!0}};function Mt(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function G(e,...t){let n=Object.create(null);for(let s in e)n[s]=e[s];return t.forEach(function(s){for(let i in s)n[i]=s[i]}),n}var Ln="</span>",ht=e=>!!e.scope,xn=(e,{prefix:t})=>{if(e.startsWith("language:"))return e.replace("language:","language-");if(e.includes(".")){let n=e.split(".");return[`${t}${n.shift()}`,...n.map((s,i)=>`${s}${"_".repeat(i+1)}`)].join(" ")}return`${t}${e}`},$e=class{constructor(t,n){this.buffer="",this.classPrefix=n.classPrefix,t.walk(this)}addText(t){this.buffer+=Mt(t)}openNode(t){if(!ht(t))return;let n=xn(t.scope,{prefix:this.classPrefix});this.span(n)}closeNode(t){ht(t)&&(this.buffer+=Ln)}value(){return this.buffer}span(t){this.buffer+=`<span class="${t}">`}},mt=(e={})=>{let t={children:[]};return Object.assign(t,e),t},He=class e{constructor(){this.rootNode=mt(),this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(t){this.top.children.push(t)}openNode(t){let n=mt({scope:t});this.add(n),this.stack.push(n)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(t){return this.constructor._walk(t,this.rootNode)}static _walk(t,n){return typeof n=="string"?t.addText(n):n.children&&(t.openNode(n),n.children.forEach(s=>this._walk(t,s)),t.closeNode(n)),t}static _collapse(t){typeof t!="string"&&t.children&&(t.children.every(n=>typeof n=="string")?t.children=[t.children.join("")]:t.children.forEach(n=>{e._collapse(n)}))}},ke=class extends He{constructor(t){super(),this.options=t}addText(t){t!==""&&this.add(t)}startScope(t){this.openNode(t)}endScope(){this.closeNode()}__addSublanguage(t,n){let s=t.root;n&&(s.scope=`language:${n}`),this.add(s)}toHTML(){return new $e(this,this.options).value()}finalize(){return this.closeAllNodes(),!0}};function le(e){return e?typeof e=="string"?e:e.source:null}function wt(e){return V("(?=",e,")")}function An(e){return V("(?:",e,")*")}function Cn(e){return V("(?:",e,")?")}function V(...e){return e.map(n=>le(n)).join("")}function Rn(e){let t=e[e.length-1];return typeof t=="object"&&t.constructor===Object?(e.splice(e.length-1,1),t):{}}function Be(...e){return"("+(Rn(e).capture?"":"?:")+e.map(s=>le(s)).join("|")+")"}function Tt(e){return new RegExp(e.toString()+"|").exec("").length-1}function Nn(e,t){let n=e&&e.exec(t);return n&&n.index===0}var On=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;function Pe(e,{joinWith:t}){let n=0;return e.map(s=>{n+=1;let i=n,c=le(s),r="";for(;c.length>0;){let o=On.exec(c);if(!o){r+=c;break}r+=c.substring(0,o.index),c=c.substring(o.index+o[0].length),o[0][0]==="\\"&&o[1]?r+="\\"+String(Number(o[1])+i):(r+=o[0],o[0]==="("&&n++)}return r}).map(s=>`(${s})`).join(t)}var In=/\b\B/,St="[a-zA-Z]\\w*",Fe="[a-zA-Z_]\\w*",Lt="\\b\\d+(\\.\\d+)?",xt="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",At="\\b(0b[01]+)",$n="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",Hn=(e={})=>{let t=/^#![ ]*\//;return e.binary&&(e.begin=V(t,/.*\b/,e.binary,/\b.*/)),G({scope:"meta",begin:t,end:/$/,relevance:0,"on:begin":(n,s)=>{n.index!==0&&s.ignoreMatch()}},e)},ae={begin:"\\\\[\\s\\S]",relevance:0},kn={scope:"string",begin:"'",end:"'",illegal:"\\n",contains:[ae]},Dn={scope:"string",begin:'"',end:'"',illegal:"\\n",contains:[ae]},Bn={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},ye=function(e,t,n={}){let s=G({scope:"comment",begin:e,end:t,contains:[]},n);s.contains.push({scope:"doctag",begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)",end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0});let i=Be("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/);return s.contains.push({begin:V(/[ ]+/,"(",i,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),s},Pn=ye("//","$"),Fn=ye("/\\*","\\*/"),Un=ye("#","$"),Wn={scope:"number",begin:Lt,relevance:0},jn={scope:"number",begin:xt,relevance:0},qn={scope:"number",begin:At,relevance:0},zn={scope:"regexp",begin:/\/(?=[^/\n]*\/)/,end:/\/[gimuy]*/,contains:[ae,{begin:/\[/,end:/\]/,relevance:0,contains:[ae]}]},Gn={scope:"title",begin:St,relevance:0},Kn={scope:"title",begin:Fe,relevance:0},Xn={begin:"\\.\\s*"+Fe,relevance:0},Zn=function(e){return Object.assign(e,{"on:begin":(t,n)=>{n.data._beginMatch=t[1]},"on:end":(t,n)=>{n.data._beginMatch!==t[1]&&n.ignoreMatch()}})},_e=Object.freeze({__proto__:null,APOS_STRING_MODE:kn,BACKSLASH_ESCAPE:ae,BINARY_NUMBER_MODE:qn,BINARY_NUMBER_RE:At,COMMENT:ye,C_BLOCK_COMMENT_MODE:Fn,C_LINE_COMMENT_MODE:Pn,C_NUMBER_MODE:jn,C_NUMBER_RE:xt,END_SAME_AS_BEGIN:Zn,HASH_COMMENT_MODE:Un,IDENT_RE:St,MATCH_NOTHING_RE:In,METHOD_GUARD:Xn,NUMBER_MODE:Wn,NUMBER_RE:Lt,PHRASAL_WORDS_MODE:Bn,QUOTE_STRING_MODE:Dn,REGEXP_MODE:zn,RE_STARTERS_RE:$n,SHEBANG:Hn,TITLE_MODE:Gn,UNDERSCORE_IDENT_RE:Fe,UNDERSCORE_TITLE_MODE:Kn});function Vn(e,t){e.input[e.index-1]==="."&&t.ignoreMatch()}function Yn(e,t){e.className!==void 0&&(e.scope=e.className,delete e.className)}function Qn(e,t){t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)",e.__beforeBegin=Vn,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords,e.relevance===void 0&&(e.relevance=0))}function Jn(e,t){Array.isArray(e.illegal)&&(e.illegal=Be(...e.illegal))}function es(e,t){if(e.match){if(e.begin||e.end)throw new Error("begin & end are not supported with match");e.begin=e.match,delete e.match}}function ts(e,t){e.relevance===void 0&&(e.relevance=1)}var ns=(e,t)=>{if(!e.beforeMatch)return;if(e.starts)throw new Error("beforeMatch cannot be used with starts");let n=Object.assign({},e);Object.keys(e).forEach(s=>{delete e[s]}),e.keywords=n.keywords,e.begin=V(n.beforeMatch,wt(n.begin)),e.starts={relevance:0,contains:[Object.assign(n,{endsParent:!0})]},e.relevance=0,delete n.beforeMatch},ss=["of","and","for","in","not","or","if","then","parent","list","value"],is="keyword";function Ct(e,t,n=is){let s=Object.create(null);return typeof e=="string"?i(n,e.split(" ")):Array.isArray(e)?i(n,e):Object.keys(e).forEach(function(c){Object.assign(s,Ct(e[c],t,c))}),s;function i(c,r){t&&(r=r.map(o=>o.toLowerCase())),r.forEach(function(o){let l=o.split("|");s[l[0]]=[c,rs(l[0],l[1])]})}}function rs(e,t){return t?Number(t):os(e)?0:1}function os(e){return ss.includes(e.toLowerCase())}var bt={},Z=e=>{console.error(e)},_t=(e,...t)=>{console.log(`WARN: ${e}`,...t)},te=(e,t)=>{bt[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),bt[`${e}/${t}`]=!0)},ve=new Error;function Rt(e,t,{key:n}){let s=0,i=e[n],c={},r={};for(let o=1;o<=t.length;o++)r[o+s]=i[o],c[o+s]=!0,s+=Tt(t[o-1]);e[n]=r,e[n]._emit=c,e[n]._multi=!0}function cs(e){if(Array.isArray(e.begin)){if(e.skip||e.excludeBegin||e.returnBegin)throw Z("skip, excludeBegin, returnBegin not compatible with beginScope: {}"),ve;if(typeof e.beginScope!="object"||e.beginScope===null)throw Z("beginScope must be object"),ve;Rt(e,e.begin,{key:"beginScope"}),e.begin=Pe(e.begin,{joinWith:""})}}function ls(e){if(Array.isArray(e.end)){if(e.skip||e.excludeEnd||e.returnEnd)throw Z("skip, excludeEnd, returnEnd not compatible with endScope: {}"),ve;if(typeof e.endScope!="object"||e.endScope===null)throw Z("endScope must be object"),ve;Rt(e,e.end,{key:"endScope"}),e.end=Pe(e.end,{joinWith:""})}}function as(e){e.scope&&typeof e.scope=="object"&&e.scope!==null&&(e.beginScope=e.scope,delete e.scope)}function us(e){as(e),typeof e.beginScope=="string"&&(e.beginScope={_wrap:e.beginScope}),typeof e.endScope=="string"&&(e.endScope={_wrap:e.endScope}),cs(e),ls(e)}function ds(e){function t(r,o){return new RegExp(le(r),"m"+(e.case_insensitive?"i":"")+(e.unicodeRegex?"u":"")+(o?"g":""))}class n{constructor(){this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}addRule(o,l){l.position=this.position++,this.matchIndexes[this.matchAt]=l,this.regexes.push([l,o]),this.matchAt+=Tt(o)+1}compile(){this.regexes.length===0&&(this.exec=()=>null);let o=this.regexes.map(l=>l[1]);this.matcherRe=t(Pe(o,{joinWith:"|"}),!0),this.lastIndex=0}exec(o){this.matcherRe.lastIndex=this.lastIndex;let l=this.matcherRe.exec(o);if(!l)return null;let d=l.findIndex((E,w)=>w>0&&E!==void 0),p=this.matchIndexes[d];return l.splice(0,d),Object.assign(l,p)}}class s{constructor(){this.rules=[],this.multiRegexes=[],this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(o){if(this.multiRegexes[o])return this.multiRegexes[o];let l=new n;return this.rules.slice(o).forEach(([d,p])=>l.addRule(d,p)),l.compile(),this.multiRegexes[o]=l,l}resumingScanAtSamePosition(){return this.regexIndex!==0}considerAll(){this.regexIndex=0}addRule(o,l){this.rules.push([o,l]),l.type==="begin"&&this.count++}exec(o){let l=this.getMatcher(this.regexIndex);l.lastIndex=this.lastIndex;let d=l.exec(o);if(this.resumingScanAtSamePosition()&&!(d&&d.index===this.lastIndex)){let p=this.getMatcher(0);p.lastIndex=this.lastIndex+1,d=p.exec(o)}return d&&(this.regexIndex+=d.position+1,this.regexIndex===this.count&&this.considerAll()),d}}function i(r){let o=new s;return r.contains.forEach(l=>o.addRule(l.begin,{rule:l,type:"begin"})),r.terminatorEnd&&o.addRule(r.terminatorEnd,{type:"end"}),r.illegal&&o.addRule(r.illegal,{type:"illegal"}),o}function c(r,o){let l=r;if(r.isCompiled)return l;[Yn,es,us,ns].forEach(p=>p(r,o)),e.compilerExtensions.forEach(p=>p(r,o)),r.__beforeBegin=null,[Qn,Jn,ts].forEach(p=>p(r,o)),r.isCompiled=!0;let d=null;return typeof r.keywords=="object"&&r.keywords.$pattern&&(r.keywords=Object.assign({},r.keywords),d=r.keywords.$pattern,delete r.keywords.$pattern),d=d||/\w+/,r.keywords&&(r.keywords=Ct(r.keywords,e.case_insensitive)),l.keywordPatternRe=t(d,!0),o&&(r.begin||(r.begin=/\B|\b/),l.beginRe=t(l.begin),!r.end&&!r.endsWithParent&&(r.end=/\B|\b/),r.end&&(l.endRe=t(l.end)),l.terminatorEnd=le(l.end)||"",r.endsWithParent&&o.terminatorEnd&&(l.terminatorEnd+=(r.end?"|":"")+o.terminatorEnd)),r.illegal&&(l.illegalRe=t(r.illegal)),r.contains||(r.contains=[]),r.contains=[].concat(...r.contains.map(function(p){return fs(p==="self"?r:p)})),r.contains.forEach(function(p){c(p,l)}),r.starts&&c(r.starts,o),l.matcher=i(l),l}if(e.compilerExtensions||(e.compilerExtensions=[]),e.contains&&e.contains.includes("self"))throw new Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");return e.classNameAliases=G(e.classNameAliases||{}),c(e)}function Nt(e){return e?e.endsWithParent||Nt(e.starts):!1}function fs(e){return e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map(function(t){return G(e,{variants:null},t)})),e.cachedVariants?e.cachedVariants:Nt(e)?G(e,{starts:e.starts?G(e.starts):null}):Object.isFrozen(e)?G(e):e}var gs="11.11.1",De=class extends Error{constructor(t,n){super(t),this.name="HTMLInjectionError",this.html=n}},Ie=Mt,Et=G,vt=Symbol("nomatch"),ps=7,Ot=function(e){let t=Object.create(null),n=Object.create(null),s=[],i=!0,c="Could not find the language '{}', did you forget to load/include a language module?",r={disableAutodetect:!0,name:"Plain text",contains:[]},o={ignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i,languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",cssSelector:"pre code",languages:null,__emitter:ke};function l(a){return o.noHighlightRe.test(a)}function d(a){let g=a.className+" ";g+=a.parentNode?a.parentNode.className:"";let b=o.languageDetectRe.exec(g);if(b){let y=U(b[1]);return y||(_t(c.replace("{}",b[1])),_t("Falling back to no-highlight mode for this block.",a)),y?b[1]:"no-highlight"}return g.split(/\s+/).find(y=>l(y)||U(y))}function p(a,g,b){let y="",S="";typeof g=="object"?(y=a,b=g.ignoreIllegals,S=g.language):(te("10.7.0","highlight(lang, code, ...args) has been deprecated."),te("10.7.0",`Please use highlight(code, options) instead.
|
|
2
|
-
https://github.com/highlightjs/highlight.js/issues/2277`),S=a,
|
|
3
|
-
`,1;if(Ne>1e5&&Ne>f.index*3)throw new Error("potential infinite loop, way more iterations than matches");return M+=m,m.length}let B=U(a);if(!B)throw Z(c.replace("{}",a)),new Error('Unknown language: "'+a+'"');let fn=ds(B),Re="",h=y||fn,ot={},L=new o.__emitter(o);dn();let M="",be=0,X=0,Ne=0,Oe=!1;try{if(B.__emitTokens)B.__emitTokens(g,L);else{for(h.matcher.considerAll();;){Ne++,Oe?Oe=!1:h.matcher.considerAll(),h.matcher.lastIndex=X;let u=h.matcher.exec(g);if(!u)break;let f=g.substring(X,u.index),m=rt(f,u);X=u.index+m}rt(g.substring(X))}return L.finalize(),Re=L.toHTML(),{language:a,value:Re,relevance:be,illegal:!1,_emitter:L,_top:h}}catch(u){if(u.message&&u.message.includes("Illegal"))return{language:a,value:Ie(g),illegal:!0,relevance:0,_illegalBy:{message:u.message,index:X,context:g.slice(X-100,X+100),mode:u.mode,resultSoFar:Re},_emitter:L};if(i)return{language:a,value:Ie(g),illegal:!1,relevance:0,errorRaised:u,_emitter:L,_top:h};throw u}}function w(a){let g={value:Ie(a),illegal:!1,relevance:0,_top:r,_emitter:new o.__emitter(o)};return g._emitter.addText(a),g}function T(a,g){g=g||o.languages||Object.keys(t);let b=w(a),y=g.filter(U).filter(ge).map(N=>E(N,a,!1));y.unshift(b);let S=y.sort((N,D)=>{if(N.relevance!==D.relevance)return D.relevance-N.relevance;if(N.language&&D.language){if(U(N.language).supersetOf===D.language)return 1;if(U(D.language).supersetOf===N.language)return-1}return 0}),[k,z]=S,he=k;return he.secondBest=z,he}function H(a,g,b){let y=g&&n[g]||b;a.classList.add("hljs"),a.classList.add(`language-${y}`)}function A(a){let g=null,b=d(a);if(l(b))return;if(pe("before:highlightElement",{el:a,language:b}),a.dataset.highlighted){console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.",a);return}if(a.children.length>0&&(o.ignoreUnescapedHTML||(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."),console.warn("https://github.com/highlightjs/highlight.js/wiki/security"),console.warn("The element with unescaped HTML:"),console.warn(a)),o.throwUnescapedHTML))throw new De("One of your code blocks includes unescaped HTML.",a.innerHTML);g=a;let y=g.textContent,S=b?p(y,{language:b,ignoreIllegals:!0}):T(y);a.innerHTML=S.value,a.dataset.highlighted="yes",H(a,b,S.language),a.result={language:S.language,re:S.relevance,relevance:S.relevance},S.secondBest&&(a.secondBest={language:S.secondBest.language,relevance:S.secondBest.relevance}),pe("after:highlightElement",{el:a,result:S,text:y})}function C(a){o=Et(o,a)}let oe=()=>{ce(),te("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")};function fe(){ce(),te("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.")}let Ae=!1;function ce(){function a(){ce()}if(document.readyState==="loading"){Ae||window.addEventListener("DOMContentLoaded",a,!1),Ae=!0;return}document.querySelectorAll(o.cssSelector).forEach(A)}function et(a,g){let b=null;try{b=g(e)}catch(y){if(Z("Language definition for '{}' could not be registered.".replace("{}",a)),i)Z(y);else throw y;b=r}b.name||(b.name=a),t[a]=b,b.rawDefinition=g.bind(null,e),b.aliases&&Ce(b.aliases,{languageName:a})}function K(a){delete t[a];for(let g of Object.keys(n))n[g]===a&&delete n[g]}function tt(){return Object.keys(t)}function U(a){return a=(a||"").toLowerCase(),t[a]||t[n[a]]}function Ce(a,{languageName:g}){typeof a=="string"&&(a=[a]),a.forEach(b=>{n[b.toLowerCase()]=g})}function ge(a){let g=U(a);return g&&!g.disableAutodetect}function sn(a){a["before:highlightBlock"]&&!a["before:highlightElement"]&&(a["before:highlightElement"]=g=>{a["before:highlightBlock"](Object.assign({block:g.el},g))}),a["after:highlightBlock"]&&!a["after:highlightElement"]&&(a["after:highlightElement"]=g=>{a["after:highlightBlock"](Object.assign({block:g.el},g))})}function rn(a){sn(a),s.push(a)}function on(a){let g=s.indexOf(a);g!==-1&&s.splice(g,1)}function pe(a,g){let b=a;s.forEach(function(y){y[b]&&y[b](g)})}function cn(a){return te("10.7.0","highlightBlock will be removed entirely in v12.0"),te("10.7.0","Please use highlightElement now."),A(a)}Object.assign(e,{highlight:p,highlightAuto:T,highlightAll:ce,highlightElement:A,highlightBlock:cn,configure:C,initHighlighting:oe,initHighlightingOnLoad:fe,registerLanguage:et,unregisterLanguage:K,listLanguages:tt,getLanguage:U,registerAliases:Ce,autoDetection:ge,inherit:Et,addPlugin:rn,removePlugin:on}),e.debugMode=function(){i=!1},e.safeMode=function(){i=!0},e.versionString=gs,e.regex={concat:V,lookahead:wt,either:Be,optional:Cn,anyNumberOfTimes:An};for(let a in _e)typeof _e[a]=="object"&&yt(_e[a]);return Object.assign(e,_e),e},ne=Ot({});ne.newInstance=()=>Ot({});It.exports=ne;ne.HighlightJS=ne;ne.default=ne});function R(e,t){return(t||document).querySelector(e)}function _(e,t){return Array.from((t||document).querySelectorAll(e))}function P(e,t,n,s){typeof n=="function"?e.addEventListener(t,n):e.addEventListener(t,function(i){let c=i.target.closest(n);c&&e.contains(c)&&s&&s.call(c,i)})}var wn={"&":"&","<":"<",">":">",'"':""","'":"'"};function I(e){return e.replace(/[&<>"']/g,t=>wn[t])}function lt(e){return J(this,null,function*(){let t=new TextEncoder().encode(e),n=yield crypto.subtle.digest("SHA-1",t);return Array.from(new Uint8Array(n,0,4),s=>s.toString(16).padStart(2,"0")).join("")})}var Tn=90,Sn=75;function F(e){return e>=Tn?"green":e>=Sn?"yellow":"red"}function O(e){return e.toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")}function j(e){return(Math.floor(e*100)/100).toFixed(2)}function at(e){return"g-"+e.replace(/[^a-zA-Z0-9_-]/gu,t=>`_${t.codePointAt(0).toString(16)}_`)}var ut=[[31536e3,"year"],[2592e3,"month"],[86400,"day"],[3600,"hour"],[60,"minute"],[1,"second"]];function dt(e){let t=Math.floor((Date.now()-e.getTime())/1e3);for(let[n,s]of ut){let i=Math.floor(t/n);if(i>=1)return i===1?`about 1 ${s} ago`:`${i} ${s}s ago`}return"just now"}function ft(e){let t=(Date.now()-e.getTime())/1e3;for(let[n]of ut){let s=Math.floor(t/n);if(s>=1){let i=(s+1)*n;return Math.max((i-t)*1e3+500,1e3)}}return 1e3}var gt={};function ee(e){return gt[e]}function pt(e){return J(this,null,function*(){let t=yield Promise.all(e.map(lt));e.forEach((n,s)=>{gt[n]=t[s]})})}var Ht=Mn($t(),1);var Ue=Ht.default;function kt(e){let t=e.regex,n="([a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?)",s=t.either(/\b([A-Z]+[a-z0-9]+)+/,/\b([A-Z]+[a-z0-9]+)+[A-Z]+/),i=t.concat(s,/(::\w+)*/),r={"variable.constant":["__FILE__","__LINE__","__ENCODING__"],"variable.language":["self","super"],keyword:["alias","and","begin","BEGIN","break","case","class","defined","do","else","elsif","end","END","ensure","for","if","in","module","next","not","or","redo","require","rescue","retry","return","then","undef","unless","until","when","while","yield",...["include","extend","prepend","public","private","protected","raise","throw"]],built_in:["proc","lambda","attr_accessor","attr_reader","attr_writer","define_method","private_constant","module_function"],literal:["true","false","nil"]},o={className:"doctag",begin:"@[A-Za-z]+"},l={begin:"#<",end:">"},d=[e.COMMENT("#","$",{contains:[o]}),e.COMMENT("^=begin","^=end",{contains:[o],relevance:10}),e.COMMENT("^__END__",e.MATCH_NOTHING_RE)],p={className:"subst",begin:/#\{/,end:/\}/,keywords:r},E={className:"string",contains:[e.BACKSLASH_ESCAPE,p],variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:/%[qQwWx]?\(/,end:/\)/},{begin:/%[qQwWx]?\[/,end:/\]/},{begin:/%[qQwWx]?\{/,end:/\}/},{begin:/%[qQwWx]?</,end:/>/},{begin:/%[qQwWx]?\//,end:/\//},{begin:/%[qQwWx]?%/,end:/%/},{begin:/%[qQwWx]?-/,end:/-/},{begin:/%[qQwWx]?\|/,end:/\|/},{begin:/\B\?(\\\d{1,3})/},{begin:/\B\?(\\x[A-Fa-f0-9]{1,2})/},{begin:/\B\?(\\u\{?[A-Fa-f0-9]{1,6}\}?)/},{begin:/\B\?(\\M-\\C-|\\M-\\c|\\c\\M-|\\M-|\\C-\\M-)[\x20-\x7e]/},{begin:/\B\?\\(c|C-)[\x20-\x7e]/},{begin:/\B\?\\?\S/},{begin:t.concat(/<<[-~]?'?/,t.lookahead(/(\w+)(?=\W)[^\n]*\n(?:[^\n]*\n)*?\s*\1\b/)),contains:[e.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,contains:[e.BACKSLASH_ESCAPE,p]})]}]},w="[1-9](_?[0-9])*|0",T="[0-9](_?[0-9])*",H={className:"number",relevance:0,variants:[{begin:`\\b(${w})(\\.(${T}))?([eE][+-]?(${T})|r)?i?\\b`},{begin:"\\b0[dD][0-9](_?[0-9])*r?i?\\b"},{begin:"\\b0[bB][0-1](_?[0-1])*r?i?\\b"},{begin:"\\b0[oO][0-7](_?[0-7])*r?i?\\b"},{begin:"\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*r?i?\\b"},{begin:"\\b0(_?[0-7])+r?i?\\b"}]},A={variants:[{match:/\(\)/},{className:"params",begin:/\(/,end:/(?=\))/,excludeBegin:!0,endsParent:!0,keywords:r}]},K=[E,{variants:[{match:[/class\s+/,i,/\s+<\s+/,i]},{match:[/\b(class|module)\s+/,i]}],scope:{2:"title.class",4:"title.class.inherited"},keywords:r},{match:[/(include|extend)\s+/,i],scope:{2:"title.class"},keywords:r},{relevance:0,match:[i,/\.new[. (]/],scope:{1:"title.class"}},{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/,className:"variable.constant"},{relevance:0,match:s,scope:"title.class"},{match:[/def/,/\s+/,n],scope:{1:"keyword",3:"title.function"},contains:[A]},{begin:e.IDENT_RE+"::"},{className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"(!|\\?)?:",relevance:0},{className:"symbol",begin:":(?!\\s)",contains:[E,{begin:n}],relevance:0},H,{className:"variable",begin:"(\\$\\W)|((\\$|@@?)(\\w+))(?=[^@$?])(?![A-Za-z])(?![@$?'])"},{className:"params",begin:/\|(?!=)/,end:/\|/,excludeBegin:!0,excludeEnd:!0,relevance:0,keywords:r},{begin:"("+e.RE_STARTERS_RE+"|unless)\\s*",keywords:"unless",contains:[{className:"regexp",contains:[e.BACKSLASH_ESCAPE,p],illegal:/\n/,variants:[{begin:"/",end:"/[a-z]*"},{begin:/%r\{/,end:/\}[a-z]*/},{begin:"%r\\(",end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}]}].concat(l,d),relevance:0}].concat(l,d);p.contains=K,A.contains=K;let ge=[{begin:/^\s*=>/,starts:{end:"$",contains:K}},{className:"meta.prompt",begin:"^("+"[>?]>"+"|"+"[\\w#]+\\(\\w+\\):\\d+:\\d+[>*]"+"|"+"(\\w+-)?\\d+\\.\\d+\\.\\d+(p\\d+)?[^\\d][^>]+>"+")(?=[ ])",starts:{end:"$",keywords:r,contains:K}}];return d.unshift(l),{name:"Ruby",aliases:["rb","gemspec","podspec","thor","irb"],keywords:r,illegal:/\/\*/,contains:[e.SHEBANG({binary:"ruby"})].concat(ge).concat(d).concat(K)}}function je(e){let t=F(e),n=j(e);return`<div class="bar-sizer"><div class="coverage-bar"><div class="coverage-bar__fill coverage-bar__fill--${t}" style="width: ${n}%"></div></div></div>`}function Y(e,t,n,s,i){let c=F(e),r=j(e),o=`<div class="coverage-cell">${je(e)}<span class="coverage-pct">${r}%</span></div>`;if(i)return`<td class="cell--coverage strong t-totals__${s}-pct ${c}">${o}</td><td class="cell--numerator strong t-totals__${s}-num">${O(t)}/</td><td class="cell--denominator strong t-totals__${s}-den">${O(n)}</td>`;let l=` data-order="${j(e)}"`;return`<td class="cell--coverage cell--${s}-pct ${c}"${l}>${o}</td><td class="cell--numerator">${O(t)}/</td><td class="cell--denominator">${O(n)}</td>`}function Me(e,t,n,s){return`<th class="cell--coverage">
|
|
1
|
+
"use strict";(()=>{var xn=Object.create;var dt=Object.defineProperty;var An=Object.getOwnPropertyDescriptor;var Cn=Object.getOwnPropertyNames;var Rn=Object.getPrototypeOf,Nn=Object.prototype.hasOwnProperty;var On=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var In=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of Cn(t))!Nn.call(e,r)&&r!==n&&dt(e,r,{get:()=>t[r],enumerable:!(s=An(t,r))||s.enumerable});return e};var Hn=(e,t,n)=>(n=e!=null?xn(Rn(e)):{},In(t||!e||!e.__esModule?dt(n,"default",{value:e,enumerable:!0}):n,e));var J=(e,t,n)=>new Promise((s,r)=>{var l=c=>{try{o(n.next(c))}catch(d){r(d)}},i=c=>{try{o(n.throw(c))}catch(d){r(d)}},o=c=>c.done?s(c.value):Promise.resolve(c.value).then(l,i);o((n=n.apply(e,t)).next())});var Bt=On((br,Dt)=>{function Tt(e){return e instanceof Map?e.clear=e.delete=e.set=function(){throw new Error("map is read-only")}:e instanceof Set&&(e.add=e.clear=e.delete=function(){throw new Error("set is read-only")}),Object.freeze(e),Object.getOwnPropertyNames(e).forEach(t=>{let n=e[t],s=typeof n;(s==="object"||s==="function")&&!Object.isFrozen(n)&&Tt(n)}),e}var ye=class{constructor(t){t.data===void 0&&(t.data={}),this.data=t.data,this.isMatchIgnored=!1}ignoreMatch(){this.isMatchIgnored=!0}};function Lt(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function G(e,...t){let n=Object.create(null);for(let s in e)n[s]=e[s];return t.forEach(function(s){for(let r in s)n[r]=s[r]}),n}var Bn="</span>",_t=e=>!!e.scope,Fn=(e,{prefix:t})=>{if(e.startsWith("language:"))return e.replace("language:","language-");if(e.includes(".")){let n=e.split(".");return[`${t}${n.shift()}`,...n.map((s,r)=>`${s}${"_".repeat(r+1)}`)].join(" ")}return`${t}${e}`},ke=class{constructor(t,n){this.buffer="",this.classPrefix=n.classPrefix,t.walk(this)}addText(t){this.buffer+=Lt(t)}openNode(t){if(!_t(t))return;let n=Fn(t.scope,{prefix:this.classPrefix});this.span(n)}closeNode(t){_t(t)&&(this.buffer+=Bn)}value(){return this.buffer}span(t){this.buffer+=`<span class="${t}">`}},vt=(e={})=>{let t={children:[]};return Object.assign(t,e),t},De=class e{constructor(){this.rootNode=vt(),this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(t){this.top.children.push(t)}openNode(t){let n=vt({scope:t});this.add(n),this.stack.push(n)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(t){return this.constructor._walk(t,this.rootNode)}static _walk(t,n){return typeof n=="string"?t.addText(n):n.children&&(t.openNode(n),n.children.forEach(s=>this._walk(t,s)),t.closeNode(n)),t}static _collapse(t){typeof t!="string"&&t.children&&(t.children.every(n=>typeof n=="string")?t.children=[t.children.join("")]:t.children.forEach(n=>{e._collapse(n)}))}},Be=class extends De{constructor(t){super(),this.options=t}addText(t){t!==""&&this.add(t)}startScope(t){this.openNode(t)}endScope(){this.closeNode()}__addSublanguage(t,n){let s=t.root;n&&(s.scope=`language:${n}`),this.add(s)}toHTML(){return new ke(this,this.options).value()}finalize(){return this.closeAllNodes(),!0}};function ae(e){return e?typeof e=="string"?e:e.source:null}function xt(e){return Z("(?=",e,")")}function Pn(e){return Z("(?:",e,")*")}function qn(e){return Z("(?:",e,")?")}function Z(...e){return e.map(n=>ae(n)).join("")}function Wn(e){let t=e[e.length-1];return typeof t=="object"&&t.constructor===Object?(e.splice(e.length-1,1),t):{}}function Pe(...e){return"("+(Wn(e).capture?"":"?:")+e.map(s=>ae(s)).join("|")+")"}function At(e){return new RegExp(e.toString()+"|").exec("").length-1}function Un(e,t){let n=e&&e.exec(t);return n&&n.index===0}var jn=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;function qe(e,{joinWith:t}){let n=0;return e.map(s=>{n+=1;let r=n,l=ae(s),i="";for(;l.length>0;){let o=jn.exec(l);if(!o){i+=l;break}i+=l.substring(0,o.index),l=l.substring(o.index+o[0].length),o[0][0]==="\\"&&o[1]?i+="\\"+String(Number(o[1])+r):(i+=o[0],o[0]==="("&&n++)}return i}).map(s=>`(${s})`).join(t)}var zn=/\b\B/,Ct="[a-zA-Z]\\w*",We="[a-zA-Z_]\\w*",Rt="\\b\\d+(\\.\\d+)?",Nt="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",Ot="\\b(0b[01]+)",Gn="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",Kn=(e={})=>{let t=/^#![ ]*\//;return e.binary&&(e.begin=Z(t,/.*\b/,e.binary,/\b.*/)),G({scope:"meta",begin:t,end:/$/,relevance:0,"on:begin":(n,s)=>{n.index!==0&&s.ignoreMatch()}},e)},ue={begin:"\\\\[\\s\\S]",relevance:0},Xn={scope:"string",begin:"'",end:"'",illegal:"\\n",contains:[ue]},Vn={scope:"string",begin:'"',end:'"',illegal:"\\n",contains:[ue]},Zn={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},we=function(e,t,n={}){let s=G({scope:"comment",begin:e,end:t,contains:[]},n);s.contains.push({scope:"doctag",begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)",end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0});let r=Pe("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/);return s.contains.push({begin:Z(/[ ]+/,"(",r,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),s},Yn=we("//","$"),Qn=we("/\\*","\\*/"),Jn=we("#","$"),es={scope:"number",begin:Rt,relevance:0},ts={scope:"number",begin:Nt,relevance:0},ns={scope:"number",begin:Ot,relevance:0},ss={scope:"regexp",begin:/\/(?=[^/\n]*\/)/,end:/\/[gimuy]*/,contains:[ue,{begin:/\[/,end:/\]/,relevance:0,contains:[ue]}]},rs={scope:"title",begin:Ct,relevance:0},is={scope:"title",begin:We,relevance:0},os={begin:"\\.\\s*"+We,relevance:0},ls=function(e){return Object.assign(e,{"on:begin":(t,n)=>{n.data._beginMatch=t[1]},"on:end":(t,n)=>{n.data._beginMatch!==t[1]&&n.ignoreMatch()}})},ve=Object.freeze({__proto__:null,APOS_STRING_MODE:Xn,BACKSLASH_ESCAPE:ue,BINARY_NUMBER_MODE:ns,BINARY_NUMBER_RE:Ot,COMMENT:we,C_BLOCK_COMMENT_MODE:Qn,C_LINE_COMMENT_MODE:Yn,C_NUMBER_MODE:ts,C_NUMBER_RE:Nt,END_SAME_AS_BEGIN:ls,HASH_COMMENT_MODE:Jn,IDENT_RE:Ct,MATCH_NOTHING_RE:zn,METHOD_GUARD:os,NUMBER_MODE:es,NUMBER_RE:Rt,PHRASAL_WORDS_MODE:Zn,QUOTE_STRING_MODE:Vn,REGEXP_MODE:ss,RE_STARTERS_RE:Gn,SHEBANG:Kn,TITLE_MODE:rs,UNDERSCORE_IDENT_RE:We,UNDERSCORE_TITLE_MODE:is});function cs(e,t){e.input[e.index-1]==="."&&t.ignoreMatch()}function as(e,t){e.className!==void 0&&(e.scope=e.className,delete e.className)}function us(e,t){t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)",e.__beforeBegin=cs,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords,e.relevance===void 0&&(e.relevance=0))}function ds(e,t){Array.isArray(e.illegal)&&(e.illegal=Pe(...e.illegal))}function fs(e,t){if(e.match){if(e.begin||e.end)throw new Error("begin & end are not supported with match");e.begin=e.match,delete e.match}}function gs(e,t){e.relevance===void 0&&(e.relevance=1)}var ps=(e,t)=>{if(!e.beforeMatch)return;if(e.starts)throw new Error("beforeMatch cannot be used with starts");let n=Object.assign({},e);Object.keys(e).forEach(s=>{delete e[s]}),e.keywords=n.keywords,e.begin=Z(n.beforeMatch,xt(n.begin)),e.starts={relevance:0,contains:[Object.assign(n,{endsParent:!0})]},e.relevance=0,delete n.beforeMatch},hs=["of","and","for","in","not","or","if","then","parent","list","value"],ms="keyword";function It(e,t,n=ms){let s=Object.create(null);return typeof e=="string"?r(n,e.split(" ")):Array.isArray(e)?r(n,e):Object.keys(e).forEach(function(l){Object.assign(s,It(e[l],t,l))}),s;function r(l,i){t&&(i=i.map(o=>o.toLowerCase())),i.forEach(function(o){let c=o.split("|");s[c[0]]=[l,bs(c[0],c[1])]})}}function bs(e,t){return t?Number(t):Es(e)?0:1}function Es(e){return hs.includes(e.toLowerCase())}var yt={},V=e=>{console.error(e)},Mt=(e,...t)=>{console.log(`WARN: ${e}`,...t)},te=(e,t)=>{yt[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),yt[`${e}/${t}`]=!0)},Me=new Error;function Ht(e,t,{key:n}){let s=0,r=e[n],l={},i={};for(let o=1;o<=t.length;o++)i[o+s]=r[o],l[o+s]=!0,s+=At(t[o-1]);e[n]=i,e[n]._emit=l,e[n]._multi=!0}function _s(e){if(Array.isArray(e.begin)){if(e.skip||e.excludeBegin||e.returnBegin)throw V("skip, excludeBegin, returnBegin not compatible with beginScope: {}"),Me;if(typeof e.beginScope!="object"||e.beginScope===null)throw V("beginScope must be object"),Me;Ht(e,e.begin,{key:"beginScope"}),e.begin=qe(e.begin,{joinWith:""})}}function vs(e){if(Array.isArray(e.end)){if(e.skip||e.excludeEnd||e.returnEnd)throw V("skip, excludeEnd, returnEnd not compatible with endScope: {}"),Me;if(typeof e.endScope!="object"||e.endScope===null)throw V("endScope must be object"),Me;Ht(e,e.end,{key:"endScope"}),e.end=qe(e.end,{joinWith:""})}}function ys(e){e.scope&&typeof e.scope=="object"&&e.scope!==null&&(e.beginScope=e.scope,delete e.scope)}function Ms(e){ys(e),typeof e.beginScope=="string"&&(e.beginScope={_wrap:e.beginScope}),typeof e.endScope=="string"&&(e.endScope={_wrap:e.endScope}),_s(e),vs(e)}function ws(e){function t(i,o){return new RegExp(ae(i),"m"+(e.case_insensitive?"i":"")+(e.unicodeRegex?"u":"")+(o?"g":""))}class n{constructor(){this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}addRule(o,c){c.position=this.position++,this.matchIndexes[this.matchAt]=c,this.regexes.push([c,o]),this.matchAt+=At(o)+1}compile(){this.regexes.length===0&&(this.exec=()=>null);let o=this.regexes.map(c=>c[1]);this.matcherRe=t(qe(o,{joinWith:"|"}),!0),this.lastIndex=0}exec(o){this.matcherRe.lastIndex=this.lastIndex;let c=this.matcherRe.exec(o);if(!c)return null;let d=c.findIndex((M,w)=>w>0&&M!==void 0),p=this.matchIndexes[d];return c.splice(0,d),Object.assign(c,p)}}class s{constructor(){this.rules=[],this.multiRegexes=[],this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(o){if(this.multiRegexes[o])return this.multiRegexes[o];let c=new n;return this.rules.slice(o).forEach(([d,p])=>c.addRule(d,p)),c.compile(),this.multiRegexes[o]=c,c}resumingScanAtSamePosition(){return this.regexIndex!==0}considerAll(){this.regexIndex=0}addRule(o,c){this.rules.push([o,c]),c.type==="begin"&&this.count++}exec(o){let c=this.getMatcher(this.regexIndex);c.lastIndex=this.lastIndex;let d=c.exec(o);if(this.resumingScanAtSamePosition()&&!(d&&d.index===this.lastIndex)){let p=this.getMatcher(0);p.lastIndex=this.lastIndex+1,d=p.exec(o)}return d&&(this.regexIndex+=d.position+1,this.regexIndex===this.count&&this.considerAll()),d}}function r(i){let o=new s;return i.contains.forEach(c=>o.addRule(c.begin,{rule:c,type:"begin"})),i.terminatorEnd&&o.addRule(i.terminatorEnd,{type:"end"}),i.illegal&&o.addRule(i.illegal,{type:"illegal"}),o}function l(i,o){let c=i;if(i.isCompiled)return c;[as,fs,Ms,ps].forEach(p=>p(i,o)),e.compilerExtensions.forEach(p=>p(i,o)),i.__beforeBegin=null,[us,ds,gs].forEach(p=>p(i,o)),i.isCompiled=!0;let d=null;return typeof i.keywords=="object"&&i.keywords.$pattern&&(i.keywords=Object.assign({},i.keywords),d=i.keywords.$pattern,delete i.keywords.$pattern),d=d||/\w+/,i.keywords&&(i.keywords=It(i.keywords,e.case_insensitive)),c.keywordPatternRe=t(d,!0),o&&(i.begin||(i.begin=/\B|\b/),c.beginRe=t(c.begin),!i.end&&!i.endsWithParent&&(i.end=/\B|\b/),i.end&&(c.endRe=t(c.end)),c.terminatorEnd=ae(c.end)||"",i.endsWithParent&&o.terminatorEnd&&(c.terminatorEnd+=(i.end?"|":"")+o.terminatorEnd)),i.illegal&&(c.illegalRe=t(i.illegal)),i.contains||(i.contains=[]),i.contains=[].concat(...i.contains.map(function(p){return Ss(p==="self"?i:p)})),i.contains.forEach(function(p){l(p,c)}),i.starts&&l(i.starts,o),c.matcher=r(c),c}if(e.compilerExtensions||(e.compilerExtensions=[]),e.contains&&e.contains.includes("self"))throw new Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");return e.classNameAliases=G(e.classNameAliases||{}),l(e)}function $t(e){return e?e.endsWithParent||$t(e.starts):!1}function Ss(e){return e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map(function(t){return G(e,{variants:null},t)})),e.cachedVariants?e.cachedVariants:$t(e)?G(e,{starts:e.starts?G(e.starts):null}):Object.isFrozen(e)?G(e):e}var Ts="11.11.1",Fe=class extends Error{constructor(t,n){super(t),this.name="HTMLInjectionError",this.html=n}},$e=Lt,wt=G,St=Symbol("nomatch"),Ls=7,kt=function(e){let t=Object.create(null),n=Object.create(null),s=[],r=!0,l="Could not find the language '{}', did you forget to load/include a language module?",i={disableAutodetect:!0,name:"Plain text",contains:[]},o={ignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i,languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",cssSelector:"pre code",languages:null,__emitter:Be};function c(a){return o.noHighlightRe.test(a)}function d(a){let g=a.className+" ";g+=a.parentNode?a.parentNode.className:"";let b=o.languageDetectRe.exec(g);if(b){let v=q(b[1]);return v||(Mt(l.replace("{}",b[1])),Mt("Falling back to no-highlight mode for this block.",a)),v?b[1]:"no-highlight"}return g.split(/\s+/).find(v=>c(v)||q(v))}function p(a,g,b){let v="",S="";typeof g=="object"?(v=a,b=g.ignoreIllegals,S=g.language):(te("10.7.0","highlight(lang, code, ...args) has been deprecated."),te("10.7.0",`Please use highlight(code, options) instead.
|
|
2
|
+
https://github.com/highlightjs/highlight.js/issues/2277`),S=a,v=g),b===void 0&&(b=!0);let k={code:v,language:S};me("before:highlight",k);let z=k.result?k.result:M(k.language,k.code,b);return z.code=k.code,me("after:highlight",z),z}function M(a,g,b,v){let S=Object.create(null);function k(u,f){return u.keywords[f]}function z(){if(!h.keywords){T.addText(y);return}let u=0;h.keywordPatternRe.lastIndex=0;let f=h.keywordPatternRe.exec(y),m="";for(;f;){m+=y.substring(u,f.index);let _=B.case_insensitive?f[0].toLowerCase():f[0],L=k(h,_);if(L){let[W,Tn]=L;if(T.addText(m),m="",S[_]=(S[_]||0)+1,S[_]<=Ls&&(_e+=Tn),W.startsWith("_"))m+=f[0];else{let Ln=B.classNameAliases[W]||W;D(f[0],Ln)}}else m+=f[0];u=h.keywordPatternRe.lastIndex,f=h.keywordPatternRe.exec(y)}m+=y.substring(u),T.addText(m)}function be(){if(y==="")return;let u=null;if(typeof h.subLanguage=="string"){if(!t[h.subLanguage]){T.addText(y);return}u=M(h.subLanguage,y,!0,ut[h.subLanguage]),ut[h.subLanguage]=u._top}else u=A(y,h.subLanguage.length?h.subLanguage:null);h.relevance>0&&(_e+=u.relevance),T.__addSublanguage(u._emitter,u.language)}function O(){h.subLanguage!=null?be():z(),y=""}function D(u,f){u!==""&&(T.startScope(f),T.addText(u),T.endScope())}function ot(u,f){let m=1,_=f.length-1;for(;m<=_;){if(!u._emit[m]){m++;continue}let L=B.classNameAliases[u[m]]||u[m],W=f[m];L?D(W,L):(y=W,z(),y=""),m++}}function lt(u,f){return u.scope&&typeof u.scope=="string"&&T.openNode(B.classNameAliases[u.scope]||u.scope),u.beginScope&&(u.beginScope._wrap?(D(y,B.classNameAliases[u.beginScope._wrap]||u.beginScope._wrap),y=""):u.beginScope._multi&&(ot(u.beginScope,f),y="")),h=Object.create(u,{parent:{value:h}}),h}function ct(u,f,m){let _=Un(u.endRe,m);if(_){if(u["on:end"]){let L=new ye(u);u["on:end"](f,L),L.isMatchIgnored&&(_=!1)}if(_){for(;u.endsParent&&u.parent;)u=u.parent;return u}}if(u.endsWithParent)return ct(u.parent,f,m)}function vn(u){return h.matcher.regexIndex===0?(y+=u[0],1):(He=!0,0)}function yn(u){let f=u[0],m=u.rule,_=new ye(m),L=[m.__beforeBegin,m["on:begin"]];for(let W of L)if(W&&(W(u,_),_.isMatchIgnored))return vn(f);return m.skip?y+=f:(m.excludeBegin&&(y+=f),O(),!m.returnBegin&&!m.excludeBegin&&(y=f)),lt(m,u),m.returnBegin?0:f.length}function Mn(u){let f=u[0],m=g.substring(u.index),_=ct(h,u,m);if(!_)return St;let L=h;h.endScope&&h.endScope._wrap?(O(),D(f,h.endScope._wrap)):h.endScope&&h.endScope._multi?(O(),ot(h.endScope,u)):L.skip?y+=f:(L.returnEnd||L.excludeEnd||(y+=f),O(),L.excludeEnd&&(y=f));do h.scope&&T.closeNode(),!h.skip&&!h.subLanguage&&(_e+=h.relevance),h=h.parent;while(h!==_.parent);return _.starts&<(_.starts,u),L.returnEnd?0:f.length}function wn(){let u=[];for(let f=h;f!==B;f=f.parent)f.scope&&u.unshift(f.scope);u.forEach(f=>T.openNode(f))}let Ee={};function at(u,f){let m=f&&f[0];if(y+=u,m==null)return O(),0;if(Ee.type==="begin"&&f.type==="end"&&Ee.index===f.index&&m===""){if(y+=g.slice(f.index,f.index+1),!r){let _=new Error(`0 width match regex (${a})`);throw _.languageName=a,_.badRule=Ee.rule,_}return 1}if(Ee=f,f.type==="begin")return yn(f);if(f.type==="illegal"&&!b){let _=new Error('Illegal lexeme "'+m+'" for mode "'+(h.scope||"<unnamed>")+'"');throw _.mode=h,_}else if(f.type==="end"){let _=Mn(f);if(_!==St)return _}if(f.type==="illegal"&&m==="")return y+=`
|
|
3
|
+
`,1;if(Ie>1e5&&Ie>f.index*3)throw new Error("potential infinite loop, way more iterations than matches");return y+=m,m.length}let B=q(a);if(!B)throw V(l.replace("{}",a)),new Error('Unknown language: "'+a+'"');let Sn=ws(B),Oe="",h=v||Sn,ut={},T=new o.__emitter(o);wn();let y="",_e=0,X=0,Ie=0,He=!1;try{if(B.__emitTokens)B.__emitTokens(g,T);else{for(h.matcher.considerAll();;){Ie++,He?He=!1:h.matcher.considerAll(),h.matcher.lastIndex=X;let u=h.matcher.exec(g);if(!u)break;let f=g.substring(X,u.index),m=at(f,u);X=u.index+m}at(g.substring(X))}return T.finalize(),Oe=T.toHTML(),{language:a,value:Oe,relevance:_e,illegal:!1,_emitter:T,_top:h}}catch(u){if(u.message&&u.message.includes("Illegal"))return{language:a,value:$e(g),illegal:!0,relevance:0,_illegalBy:{message:u.message,index:X,context:g.slice(X-100,X+100),mode:u.mode,resultSoFar:Oe},_emitter:T};if(r)return{language:a,value:$e(g),illegal:!1,relevance:0,errorRaised:u,_emitter:T,_top:h};throw u}}function w(a){let g={value:$e(a),illegal:!1,relevance:0,_top:i,_emitter:new o.__emitter(o)};return g._emitter.addText(a),g}function A(a,g){g=g||o.languages||Object.keys(t);let b=w(a),v=g.filter(q).filter(he).map(O=>M(O,a,!1));v.unshift(b);let S=v.sort((O,D)=>{if(O.relevance!==D.relevance)return D.relevance-O.relevance;if(O.language&&D.language){if(q(O.language).supersetOf===D.language)return 1;if(q(D.language).supersetOf===O.language)return-1}return 0}),[k,z]=S,be=k;return be.secondBest=z,be}function $(a,g,b){let v=g&&n[g]||b;a.classList.add("hljs"),a.classList.add(`language-${v}`)}function C(a){let g=null,b=d(a);if(c(b))return;if(me("before:highlightElement",{el:a,language:b}),a.dataset.highlighted){console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.",a);return}if(a.children.length>0&&(o.ignoreUnescapedHTML||(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."),console.warn("https://github.com/highlightjs/highlight.js/wiki/security"),console.warn("The element with unescaped HTML:"),console.warn(a)),o.throwUnescapedHTML))throw new Fe("One of your code blocks includes unescaped HTML.",a.innerHTML);g=a;let v=g.textContent,S=b?p(v,{language:b,ignoreIllegals:!0}):A(v);a.innerHTML=S.value,a.dataset.highlighted="yes",$(a,b,S.language),a.result={language:S.language,re:S.relevance,relevance:S.relevance},S.secondBest&&(a.secondBest={language:S.secondBest.language,relevance:S.secondBest.relevance}),me("after:highlightElement",{el:a,result:S,text:v})}function N(a){o=wt(o,a)}let le=()=>{ce(),te("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")};function pe(){ce(),te("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.")}let Re=!1;function ce(){function a(){ce()}if(document.readyState==="loading"){Re||window.addEventListener("DOMContentLoaded",a,!1),Re=!0;return}document.querySelectorAll(o.cssSelector).forEach(C)}function rt(a,g){let b=null;try{b=g(e)}catch(v){if(V("Language definition for '{}' could not be registered.".replace("{}",a)),r)V(v);else throw v;b=i}b.name||(b.name=a),t[a]=b,b.rawDefinition=g.bind(null,e),b.aliases&&Ne(b.aliases,{languageName:a})}function K(a){delete t[a];for(let g of Object.keys(n))n[g]===a&&delete n[g]}function it(){return Object.keys(t)}function q(a){return a=(a||"").toLowerCase(),t[a]||t[n[a]]}function Ne(a,{languageName:g}){typeof a=="string"&&(a=[a]),a.forEach(b=>{n[b.toLowerCase()]=g})}function he(a){let g=q(a);return g&&!g.disableAutodetect}function mn(a){a["before:highlightBlock"]&&!a["before:highlightElement"]&&(a["before:highlightElement"]=g=>{a["before:highlightBlock"](Object.assign({block:g.el},g))}),a["after:highlightBlock"]&&!a["after:highlightElement"]&&(a["after:highlightElement"]=g=>{a["after:highlightBlock"](Object.assign({block:g.el},g))})}function bn(a){mn(a),s.push(a)}function En(a){let g=s.indexOf(a);g!==-1&&s.splice(g,1)}function me(a,g){let b=a;s.forEach(function(v){v[b]&&v[b](g)})}function _n(a){return te("10.7.0","highlightBlock will be removed entirely in v12.0"),te("10.7.0","Please use highlightElement now."),C(a)}Object.assign(e,{highlight:p,highlightAuto:A,highlightAll:ce,highlightElement:C,highlightBlock:_n,configure:N,initHighlighting:le,initHighlightingOnLoad:pe,registerLanguage:rt,unregisterLanguage:K,listLanguages:it,getLanguage:q,registerAliases:Ne,autoDetection:he,inherit:wt,addPlugin:bn,removePlugin:En}),e.debugMode=function(){r=!1},e.safeMode=function(){r=!0},e.versionString=Ts,e.regex={concat:Z,lookahead:xt,either:Pe,optional:qn,anyNumberOfTimes:Pn};for(let a in ve)typeof ve[a]=="object"&&Tt(ve[a]);return Object.assign(e,ve),e},ne=kt({});ne.newInstance=()=>kt({});Dt.exports=ne;ne.HighlightJS=ne;ne.default=ne});function R(e,t){return(t||document).querySelector(e)}function E(e,t){return Array.from((t||document).querySelectorAll(e))}function F(e,t,n,s){typeof n=="function"?e.addEventListener(t,n):e.addEventListener(t,function(r){let l=r.target.closest(n);l&&e.contains(l)&&s&&s.call(l,r)})}var $n={"&":"&","<":"<",">":">",'"':""","'":"'"};function I(e){return e.replace(/[&<>"']/g,t=>$n[t])}function ft(e){return J(this,null,function*(){let t=new TextEncoder().encode(e),n=yield crypto.subtle.digest("SHA-1",t);return Array.from(new Uint8Array(n,0,4),s=>s.toString(16).padStart(2,"0")).join("")})}var kn=90,Dn=75;function P(e){return e>=kn?"green":e>=Dn?"yellow":"red"}function x(e){return e.toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")}function U(e){return(Math.floor(e*100)/100).toFixed(2)}function gt(e){return"g-"+e.replace(/[^a-zA-Z0-9_-]/gu,t=>`_${t.codePointAt(0).toString(16)}_`)}var pt=[[31536e3,"year"],[2592e3,"month"],[86400,"day"],[3600,"hour"],[60,"minute"],[1,"second"]];function ht(e){let t=Math.floor((Date.now()-e.getTime())/1e3);for(let[n,s]of pt){let r=Math.floor(t/n);if(r>=1)return r===1?`about 1 ${s} ago`:`${r} ${s}s ago`}return"just now"}function mt(e){let t=(Date.now()-e.getTime())/1e3;for(let[n]of pt){let s=Math.floor(t/n);if(s>=1){let r=(s+1)*n;return Math.max((r-t)*1e3+500,1e3)}}return 1e3}var bt={};function ee(e){return bt[e]}function Et(e){return J(this,null,function*(){let t=yield Promise.all(e.map(ft));e.forEach((n,s)=>{bt[n]=t[s]})})}var Ft=Hn(Bt(),1);var Ue=Ft.default;function Pt(e){let t=e.regex,n="([a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?)",s=t.either(/\b([A-Z]+[a-z0-9]+)+/,/\b([A-Z]+[a-z0-9]+)+[A-Z]+/),r=t.concat(s,/(::\w+)*/),i={"variable.constant":["__FILE__","__LINE__","__ENCODING__"],"variable.language":["self","super"],keyword:["alias","and","begin","BEGIN","break","case","class","defined","do","else","elsif","end","END","ensure","for","if","in","module","next","not","or","redo","require","rescue","retry","return","then","undef","unless","until","when","while","yield",...["include","extend","prepend","public","private","protected","raise","throw"]],built_in:["proc","lambda","attr_accessor","attr_reader","attr_writer","define_method","private_constant","module_function"],literal:["true","false","nil"]},o={className:"doctag",begin:"@[A-Za-z]+"},c={begin:"#<",end:">"},d=[e.COMMENT("#","$",{contains:[o]}),e.COMMENT("^=begin","^=end",{contains:[o],relevance:10}),e.COMMENT("^__END__",e.MATCH_NOTHING_RE)],p={className:"subst",begin:/#\{/,end:/\}/,keywords:i},M={className:"string",contains:[e.BACKSLASH_ESCAPE,p],variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:/%[qQwWx]?\(/,end:/\)/},{begin:/%[qQwWx]?\[/,end:/\]/},{begin:/%[qQwWx]?\{/,end:/\}/},{begin:/%[qQwWx]?</,end:/>/},{begin:/%[qQwWx]?\//,end:/\//},{begin:/%[qQwWx]?%/,end:/%/},{begin:/%[qQwWx]?-/,end:/-/},{begin:/%[qQwWx]?\|/,end:/\|/},{begin:/\B\?(\\\d{1,3})/},{begin:/\B\?(\\x[A-Fa-f0-9]{1,2})/},{begin:/\B\?(\\u\{?[A-Fa-f0-9]{1,6}\}?)/},{begin:/\B\?(\\M-\\C-|\\M-\\c|\\c\\M-|\\M-|\\C-\\M-)[\x20-\x7e]/},{begin:/\B\?\\(c|C-)[\x20-\x7e]/},{begin:/\B\?\\?\S/},{begin:t.concat(/<<[-~]?'?/,t.lookahead(/(\w+)(?=\W)[^\n]*\n(?:[^\n]*\n)*?\s*\1\b/)),contains:[e.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,contains:[e.BACKSLASH_ESCAPE,p]})]}]},w="[1-9](_?[0-9])*|0",A="[0-9](_?[0-9])*",$={className:"number",relevance:0,variants:[{begin:`\\b(${w})(\\.(${A}))?([eE][+-]?(${A})|r)?i?\\b`},{begin:"\\b0[dD][0-9](_?[0-9])*r?i?\\b"},{begin:"\\b0[bB][0-1](_?[0-1])*r?i?\\b"},{begin:"\\b0[oO][0-7](_?[0-7])*r?i?\\b"},{begin:"\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*r?i?\\b"},{begin:"\\b0(_?[0-7])+r?i?\\b"}]},C={variants:[{match:/\(\)/},{className:"params",begin:/\(/,end:/(?=\))/,excludeBegin:!0,endsParent:!0,keywords:i}]},K=[M,{variants:[{match:[/class\s+/,r,/\s+<\s+/,r]},{match:[/\b(class|module)\s+/,r]}],scope:{2:"title.class",4:"title.class.inherited"},keywords:i},{match:[/(include|extend)\s+/,r],scope:{2:"title.class"},keywords:i},{relevance:0,match:[r,/\.new[. (]/],scope:{1:"title.class"}},{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/,className:"variable.constant"},{relevance:0,match:s,scope:"title.class"},{match:[/def/,/\s+/,n],scope:{1:"keyword",3:"title.function"},contains:[C]},{begin:e.IDENT_RE+"::"},{className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"(!|\\?)?:",relevance:0},{className:"symbol",begin:":(?!\\s)",contains:[M,{begin:n}],relevance:0},$,{className:"variable",begin:"(\\$\\W)|((\\$|@@?)(\\w+))(?=[^@$?])(?![A-Za-z])(?![@$?'])"},{className:"params",begin:/\|(?!=)/,end:/\|/,excludeBegin:!0,excludeEnd:!0,relevance:0,keywords:i},{begin:"("+e.RE_STARTERS_RE+"|unless)\\s*",keywords:"unless",contains:[{className:"regexp",contains:[e.BACKSLASH_ESCAPE,p],illegal:/\n/,variants:[{begin:"/",end:"/[a-z]*"},{begin:/%r\{/,end:/\}[a-z]*/},{begin:"%r\\(",end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}]}].concat(c,d),relevance:0}].concat(c,d);p.contains=K,C.contains=K;let he=[{begin:/^\s*=>/,starts:{end:"$",contains:K}},{className:"meta.prompt",begin:"^("+"[>?]>"+"|"+"[\\w#]+\\(\\w+\\):\\d+:\\d+[>*]"+"|"+"(\\w+-)?\\d+\\.\\d+\\.\\d+(p\\d+)?[^\\d][^>]+>"+")(?=[ ])",starts:{end:"$",keywords:i,contains:K}}];return d.unshift(c),{name:"Ruby",aliases:["rb","gemspec","podspec","thor","irb"],keywords:i,illegal:/\/\*/,contains:[e.SHEBANG({binary:"ruby"})].concat(he).concat(d).concat(K)}}function ze(e){let t=P(e),n=U(e);return`<div class="bar-sizer"><div class="coverage-bar"><div class="coverage-bar__fill coverage-bar__fill--${t}" style="width: ${n}%"></div></div></div>`}function Y(e,t,n,s,r){let l=P(e),i=U(e),o=`<div class="coverage-cell">${ze(e)}<span class="coverage-pct">${i}%</span></div>`;if(r)return`<td class="cell--coverage strong t-totals__${s}-pct ${l}">${o}</td><td class="cell--numerator strong t-totals__${s}-num">${x(t)}/</td><td class="cell--denominator strong t-totals__${s}-den">${x(n)}</td>`;let c=` data-order="${U(e)}"`;return`<td class="cell--coverage cell--${s}-pct ${l}"${c}>${o}</td><td class="cell--numerator">${x(t)}/</td><td class="cell--denominator">${x(n)}</td>`}function Se(e,t,n,s){return`<th class="cell--coverage">
|
|
4
4
|
<div class="th-with-filter">
|
|
5
5
|
<span class="th-label">${e}</span>
|
|
6
6
|
<div class="col-filter__coverage">
|
|
@@ -10,9 +10,9 @@ https://github.com/highlightjs/highlight.js/issues/2277`),S=a,y=g),b===void 0&&(
|
|
|
10
10
|
</div>
|
|
11
11
|
</th>
|
|
12
12
|
<th class="cell--numerator">${n}</th>
|
|
13
|
-
<th class="cell--denominator">${s}</th>`}function
|
|
13
|
+
<th class="cell--denominator">${s}</th>`}function je(e){let{type:t,label:n,covered:s,total:r,enabled:l,toggle:i}=e;if(!l)return`<div class="t-${t}-summary">
|
|
14
14
|
${n}: <span class="coverage-disabled">disabled</span>
|
|
15
|
-
</div>`;let o=
|
|
16
|
-
${n}: <span class="${d}"><b>${
|
|
17
|
-
${
|
|
18
|
-
</div>`,w}function Dt(e){return'<div class="summary-stats">'+We({type:"line",label:"Line coverage",covered:e.coveredLines,total:e.totalLines,enabled:!0,suffix:"relevant lines covered"})+We({type:"branch",label:"Branch coverage",covered:e.coveredBranches,total:e.totalBranches,enabled:e.branchCoverage,missedClass:"missed-branch-text"})+We({type:"method",label:"Method coverage",covered:e.coveredMethods,total:e.totalMethods,enabled:e.methodCoverage,missedClass:"missed-method-text-color",toggle:e.showMethodToggle})+"</div>"}function hs(e){let{title:t,filenames:n,stats:s,branchCoverage:i,methodCoverage:c}=e,r=at(t),o=s.lines,l=i?s.branches:void 0,d=c?s.methods:void 0,p=[`<div class="file_list_container" id="${r}" data-total-files="${n.length}">`,`<span class="group_name hide">${I(t)}</span>`,`<span class="covered_percent hide"><span class="${F(o.percent)}">${j(o.percent)}%</span></span>`,'<div class="file_list--responsive"><table class="file_list"><thead><tr>','<th class="cell--left"><div class="th-with-filter"><span class="th-label">File Name</span><input type="search" class="col-filter col-filter--name" placeholder="Filter paths\u2026"></div></th>',Me("Line Coverage","line","Covered","Lines")];i&&p.push(Me("Branch Coverage","branch","Covered","Branches")),c&&p.push(Me("Method Coverage","method","Covered","Methods")),p.push("</tr>");let E=n.length===1?"file":"files";return p.push(`<tr class="totals-row"><td class="strong t-file-count">${O(n.length)} ${E}</td>`,Y(o.percent,o.covered,o.total,"line",!0)),l&&p.push(Y(l.percent,l.covered,l.total,"branch",!0)),d&&p.push(Y(d.percent,d.covered,d.total,"method",!0)),p.push("</tr></thead><tbody>"),p.join("")}function ms(e){let{filename:t,coverage:n,branchCoverage:s,methodCoverage:i}=e,c=ee(t),r=[`data-covered-lines="${n.covered_lines}"`,`data-relevant-lines="${n.total_lines}"`];s&&r.push(`data-covered-branches="${n.covered_branches||0}"`,`data-total-branches="${n.total_branches||0}"`),i&&r.push(`data-covered-methods="${n.covered_methods||0}"`,`data-total-methods="${n.total_methods||0}"`);let o=[`<tr class="t-file" ${r.join(" ")}>`,`<td class="strong t-file__name"><a href="#${c}" class="src_link" title="${I(t)}">${I(t)}</a></td>`,Y(n.lines_covered_percent,n.covered_lines,n.total_lines,"line",!1)];if(s){let l=n.branches_covered_percent===void 0?100:n.branches_covered_percent;o.push(Y(l,n.covered_branches||0,n.total_branches||0,"branch",!1))}if(i){let l=n.methods_covered_percent===void 0?100:n.methods_covered_percent;o.push(Y(l,n.covered_methods||0,n.total_methods||0,"method",!1))}return o.push("</tr>"),o.join("")}function qe(e){let{filenames:t,allCoverage:n,branchCoverage:s,methodCoverage:i}=e,c=[hs(e)];for(let r of t){let o=n[r];o&&c.push(ms({filename:r,coverage:o,branchCoverage:s,methodCoverage:i}))}return c.push("</tbody></table></div></div>"),c.join("")}function bs(e){let{lineIndex:t,lineCov:n,branchesReport:s,missedMethodLines:i,branchCoverage:c,methodCoverage:r}=e,o=t+1;if(n==="ignored")return"skipped";if(c){let l=s[o];if(l&&l.some(([,d])=>d===0))return"missed-branch"}return r&&i.has(o)?"missed-method":n===null?"never":n===0?"missed":"covered"}function _s(e){let t={};if(!e)return t;for(let{coverage:n,report_line:s,type:i}of e){if(n==="ignored")continue;(t[s]||(t[s]=[])).push([i,n])}return t}function Es(e){let t=new Set;if(!e)return t;for(let n of e)if(n.coverage===0&&n.start_line&&n.end_line)for(let s=n.start_line;s<=n.end_line;s++)t.add(s);return t}function vs(e){let{index:t,source:n,lineCov:s,status:i,branchCoverage:c,lineBranches:r}=e,o=t+1,l=s!==null&&s!=="ignored"?` data-hits="${s}"`:"",d=[`<li class="${i}"${l} data-linenumber="${o}">`];if(i==="covered"||s!==null&&s!=="ignored"&&s!==0?d.push(`<span class="hits" data-content="${s}"></span>`):s==="ignored"&&d.push('<span class="hits" data-content="skipped"></span>'),c&&r)for(let[p,E]of r){let w=I(p);d.push(`<span class="hits" data-content="${w}: ${E}" title="${w} branch hit ${E} times"></span>`)}return d.push(`<code class="ruby">${I(n)}</code></li>`),d.join("")}function Bt(e,t,n,s){let i=ee(e),c=t.covered_lines,r=t.total_lines,o=n&&t.covered_branches||0,l=n&&t.total_branches||0,d=s&&t.covered_methods||0,p=s&&t.total_methods||0,E=(t.methods||[]).filter(C=>C.coverage===0),w=s&&E.length>0,T=_s(t.branches),H=Es(t.methods),A=[`<div class="source_table" id="${i}">`,'<div class="header">',`<h2>${I(e)}</h2>`,Dt({coveredLines:c,totalLines:r,coveredBranches:o,totalBranches:l,coveredMethods:d,totalMethods:p,branchCoverage:n,methodCoverage:s,showMethodToggle:w})];w&&A.push('<div class="t-missed-method-list" style="display: none"><ul>',E.map(C=>`<li><tt>${I(C.name)}</tt></li>`).join(""),"</ul></div>"),A.push("</div>","<pre><ol>");for(let C=0;C<t.source.length;C++){let oe=t.lines[C],fe=bs({lineIndex:C,lineCov:oe,branchesReport:T,missedMethodLines:H,branchCoverage:n,methodCoverage:s});A.push(vs({index:C,source:t.source[C],lineCov:oe,status:fe,branchCoverage:n,lineBranches:n?T[C+1]:void 0}))}return A.push("</ol></pre></div>"),A.join("")}Ue.registerLanguage("ruby",kt);var se=null;function Pt(e){let t=e.meta,n=t.branch_coverage,s=t.method_coverage;document.title=`Code coverage for ${t.project_name}`;let i=Object.keys(e.coverage),c=e.total.lines.total>0?e.total.lines.percent:100,r=document.createElement("link");r.rel="icon",r.type="image/png",r.href=`favicon_${F(c)}.png`,document.head.appendChild(r),n&&document.body.setAttribute("data-branch-coverage","true");let o=document.getElementById("content"),l=[qe({title:"All Files",filenames:i,stats:e.total,allCoverage:e.coverage,branchCoverage:n,methodCoverage:s})];for(let H of Object.keys(e.groups)){let A=e.groups[H];l.push(qe({title:H,filenames:A.files||[],stats:A,allCoverage:e.coverage,branchCoverage:n,methodCoverage:s}))}o.innerHTML=l.join("");let d={};for(let H of i)d[ee(H)]=H;se={idToFilename:d,coverage:e.coverage,branchCoverage:n,methodCoverage:s};let p=new Date(t.timestamp),E=document.getElementById("footer");E.innerHTML=`Generated <abbr class="timeago" title="${p.toISOString()}">${p.toISOString()}</abbr> by <a href="https://github.com/simplecov-ruby/simplecov">simplecov</a> v${I(t.simplecov_version)} using ${I(t.command_name)}`;let w=document.getElementById("source-legend"),T='<span class="source-legend__item"><span class="source-legend__swatch source-legend__swatch--covered"></span>Covered</span><span class="source-legend__item"><span class="source-legend__swatch source-legend__swatch--skipped"></span>Skipped</span><span class="source-legend__item"><span class="source-legend__swatch source-legend__swatch--missed"></span>Missed line</span>';n&&(T+='<span class="source-legend__item"><span class="source-legend__swatch source-legend__swatch--missed-branch"></span>Missed branch</span>'),s&&(T+='<span class="source-legend__item"><span class="source-legend__swatch source-legend__swatch--missed-method"></span>Missed method</span>'),w.innerHTML=T}function Ft(e){let t=document.getElementById(e);if(t)return t;if(!se)return null;let n=se.idToFilename[e];if(!n)return null;let s=Bt(n,se.coverage[n],se.branchCoverage,se.methodCoverage),i=document.querySelector(".source_files"),c=document.createElement("div");c.innerHTML=s;let r=c.firstElementChild;return i.appendChild(r),_("pre code",r).forEach(o=>Ue.highlightElement(o)),r}var Ut={};function ys(e,t){var s;return(s=Array.from(e.children).filter(i=>i.style.display!=="none")[t])!=null?s:null}function Ms(e){if(!e)return"";let t=e.getAttribute("data-order");if(t!==null)return Number.parseFloat(t);let n=(e.textContent||"").trim(),s=Number.parseFloat(n);return Number.isNaN(s)?n.toLowerCase():s}function ws(e,t){let n=e.id||e.getAttribute("data-sort-id")||"default",s=Ut[n],i=s&&s.colIndex===t&&s.direction==="asc"?"desc":"asc";Ut[n]={colIndex:t,direction:i};let c=e.querySelector("tbody"),r=Array.from(c.querySelectorAll("tr.t-file")).map(d=>({row:d,value:Ms(ys(d,t))}));r.sort((d,p)=>{let E=d.value,w=p.value,T;return typeof E=="number"&&typeof w=="number"?T=E-w:T=String(E).localeCompare(String(w)),i==="asc"?T:-T});let o=document.createDocumentFragment();r.forEach(({row:d})=>o.appendChild(d)),c.appendChild(o);let l=0;_("thead tr:first-child th",e).forEach(d=>{let p=Number.parseInt(d.getAttribute("colspan")||"1",10);d.classList.remove("sorting_asc","sorting_desc","sorting");let E=t>=l&&t<l+p;d.classList.add(E?i==="asc"?"sorting_asc":"sorting_desc":"sorting"),l+=p})}function Ts(e,t){let n=0;for(let s of _("thead tr:first-child th",e)){let i=Number.parseInt(s.getAttribute("colspan")||"1",10);if(s===t)return n+i-1;n+=i}return n}function Wt(){_("table.file_list").forEach(e=>{_("thead tr:first-child th",e).forEach(t=>{t.classList.add("sorting"),t.style.cursor="pointer",t.addEventListener("click",()=>ws(e,Ts(e,t)))})})}var ue=null;function we(){ue=null}function jt(){if(ue)return ue;let e=_(".file_list_container").filter(t=>t.style.display!=="none");return e.length?(ue=_("tbody tr.t-file",e[0]).filter(t=>t.style.display!=="none"),ue):[]}var Ss=240,Ls=160;function qt(e,t){let n=t+"px";e.forEach(s=>{let i=s.style;i.width=n,i.minWidth=n,i.maxWidth=n})}function Ge(){_(".file_list_container").forEach(e=>{if(e.style.display==="none"||e.offsetWidth===0)return;let t=R("table.file_list",e);if(!t)return;let n=_(".bar-sizer",t);if(n.length===0)return;let s=t.closest(".file_list--responsive");if(!s)return;s.style.visibility="hidden";let i=Ls,c=Ss;for(;i<c;){let r=Math.ceil((i+c)/2);qt(n,r),t.offsetWidth,t.scrollWidth<=s.clientWidth?i=r:c=r-1}qt(n,i),s.style.visibility=""})}var ze=0;function ie(){ze||(ze=requestAnimationFrame(()=>{ze=0,Ge()}))}var Te={line:{covered:"coveredLines",total:"relevantLines"},branch:{covered:"coveredBranches",total:"totalBranches"},method:{covered:"coveredMethods",total:"totalMethods"}};function zt(e){let t=_("tbody tr.t-file",e).filter(c=>c.style.display!=="none");function n(c){return t.reduce((r,o)=>r+(Number.parseInt(o.dataset[c]||"0",10)||0),0)}let s=R(".t-file-count",e),i=Number.parseInt(e.getAttribute("data-total-files")||"0",10);if(s){let c=t.length===1?" file":" files";s.textContent=t.length===i?O(i)+c:O(t.length)+"/"+O(i)+c}for(let c of Object.keys(Te)){let r=Te[c],o=`.t-totals__${c}`;R(o+"-pct",e)&&xs(e,o,n(r.covered),n(r.total))}}function xs(e,t,n,s){let i=R(t+"-pct",e),c=R(t+"-num",e),r=R(t+"-den",e);if(s===0){i&&(i.innerHTML="",i.classList.remove("green","yellow","red")),c&&(c.textContent=""),r&&(r.textContent="");return}let o=n*100/s,l=F(o);i&&(i.innerHTML=`<div class="coverage-cell">${je(o)}<span class="coverage-pct">${j(o)}%</span></div>`,i.classList.remove("green","yellow","red"),i.classList.add(l)),c&&(c.textContent=O(n)+"/"),r&&(r.textContent=O(s))}var As={gt:(e,t)=>e>t,gte:(e,t)=>e>=t,eq:(e,t)=>e===t,lte:(e,t)=>e<=t,lt:(e,t)=>e<t};function Cs(e,t,n){let s=As[e];return s?s(t,n):!0}function Rs(e){let t=[];for(let n of _(".col-filter__value",e)){let s=n;if(!s.value)continue;let i=Number.parseFloat(s.value);if(Number.isNaN(i))continue;let c=s.dataset.type||"",r=R(`.col-filter__op[data-type="${c}"]`,e),o=r?r.value:"",l=Te[c];o&&l&&t.push({attrs:l,op:o,threshold:i})}return t}function Gt(e){let t=R("table.file_list",e);if(!t)return;let n=R(".col-filter--name",e),s=n?n.value.trim().toLowerCase():"",i=Rs(e);_("tbody tr.t-file",t).forEach(c=>{let r=c,o=(c.children[0].textContent||"").toLowerCase(),l=(!s||o.includes(s))&&i.every(d=>{let p=Number.parseInt(r.dataset[d.attrs.covered]||"0",10)||0,E=Number.parseInt(r.dataset[d.attrs.total]||"0",10)||0,w=E>0?p*100/E:100;return Cs(d.op,w,d.threshold)});r.style.display=l?"":"none"}),we(),zt(e),ie()}function Ke(e){let t=Number.parseFloat(e.value),n=e.closest(".col-filter__coverage"),s=n?n.querySelector(".col-filter__op"):null;if(!s)return;let i=s.querySelector('option[value="gt"]'),c=s.querySelector('option[value="lt"]');if(i&&(i.disabled=t>=100),c&&(c.disabled=t<=0),s.selectedOptions[0]&&s.selectedOptions[0].disabled){let r=s.querySelector("option:not(:disabled)");r&&(s.value=r.value)}}function Kt(){_(".col-filter__value").forEach(e=>Ke(e)),_(".col-filter--name, .col-filter__op, .col-filter__value, .col-filter__coverage").forEach(e=>{e.addEventListener("click",t=>t.stopPropagation())}),P(document,"input",".col-filter--name, .col-filter__op, .col-filter__value",function(){this.classList.contains("col-filter__value")&&Ke(this),Gt(this.closest(".file_list_container"))}),P(document,"change",".col-filter__op, .col-filter__value",function(){this.classList.contains("col-filter__value")&&Ke(this),Gt(this.closest(".file_list_container"))})}var $=null;function Xe(){return $!==null}function re(e){$&&$.classList.remove("keyboard-focus"),$=e,$&&($.classList.add("keyboard-focus"),$.scrollIntoView({block:"nearest"}))}function Ze(e){let t=jt();if(!t.length)return;if(!$||t.indexOf($)===-1){re(e===1?t[0]:t[t.length-1]);return}let n=t.indexOf($)+e;n>=0&&n<t.length&&re(t[n])}function Xt(){if(!$)return;let e=$.querySelector("a.src_link");e&&(window.location.hash=e.getAttribute("href").substring(1))}var q,Q,Ve,de=null,Se="";function Ye(){return q.open}function Qe(){return Q}function Vt(){if(!de)return;Se&&(de.insertAdjacentHTML("afterbegin",Se),Se="");let e=document.querySelector(".source_files");e&&e.appendChild(de),de=null}function Ns(e,t){Vt();let n=Ft(e);if(!n)return;let s=n.querySelector(".header");if(s&&(Se=s.outerHTML,Ve.innerHTML=s.innerHTML,s.remove()),de=n,Q.appendChild(n),q.open||q.showModal(),document.documentElement.style.overflow="hidden",Q.focus(),t){let i=Q.querySelector('li[data-linenumber="'+t+'"]');i&&(Q.scrollTop=i.offsetTop)}}function Zt(e){if(re(null),we(),q.open&&(Vt(),q.close(),Q.innerHTML="",Ve.innerHTML="",document.documentElement.style.overflow=""),e){let n=document.querySelector(".group_tabs a."+e);if(n){_(".group_tabs li").forEach(i=>i.classList.remove("active")),n.parentElement.classList.add("active"),_(".file_list_container").forEach(i=>i.style.display="none");let s=document.getElementById(e);s&&(s.style.display="")}}let t=document.getElementById("wrapper");t&&!t.classList.contains("hide")&&ie()}function xe(){let e=window.location.hash.substring(1);if(!e){let t=document.querySelector(".group_tabs a");t&&Zt(t.getAttribute("href").replace("#",""));return}if(e.charAt(0)==="_")Zt(e.substring(1));else{let t=e.split("-L");if(!document.querySelector(".group_tabs li.active")){let n=document.querySelector(".group_tabs li");n&&n.classList.add("active")}Ns(t[0],t[1])}}function Le(){let e=document.querySelector(".group_tabs li.active a");e&&(window.location.hash=e.getAttribute("href").replace("#","#_"))}function Yt(){q=document.getElementById("source-dialog"),Q=document.getElementById("source-dialog-body"),Ve=document.getElementById("source-dialog-title"),q.querySelector(".source-dialog__close").addEventListener("click",Le),q.addEventListener("click",e=>{e.target===q&&Le()})}function Os(){return _(".source-dialog .source_table li.missed, .source-dialog .source_table li.missed-branch, .source-dialog .source_table li.missed-method")}function Je(e){let t=Os();if(!t.length)return;let n=Qe(),s=n.scrollTop+n.clientHeight/2,i=e===1?t.find(c=>c.offsetTop>s)||t[0]:t.findLast(c=>c.offsetTop<s-10)||t[t.length-1];n.scrollTop=i.offsetTop-n.clientHeight/3}function Qt(){P(document,"click",".t-missed-method-toggle",function(e){e.preventDefault();let t=this.closest(".header")||this.closest(".source-dialog__title")||this.closest(".source-dialog__header"),n=t?t.querySelector(".t-missed-method-list"):null;n&&(n.style.display=n.style.display==="none"?"":"none")}),P(document,"click","a.src_link",function(e){e.preventDefault(),window.location.hash=this.getAttribute("href").substring(1)}),P(document,"click","table.file_list tbody tr",function(e){if(e.target.closest("a"))return;let t=this.querySelector("a.src_link");t&&(window.location.hash=t.getAttribute("href").substring(1))}),P(document,"click",".source-dialog .source_table li[data-linenumber]",function(e){e.preventDefault(),Qe().scrollTop=this.offsetTop;let t=this.dataset.linenumber,n=window.location.hash.substring(1).replace(/-L.*/,"");window.location.replace(window.location.href.replace(/#.*/,"#"+n+"-L"+t))}),window.addEventListener("hashchange",xe)}var Jt="simplecov-dark-mode";function Is(){try{return localStorage.getItem(Jt)}catch(e){return null}}function $s(e){try{localStorage.setItem(Jt,e)}catch(t){}}function en(){let e=document.getElementById("dark-mode-toggle");if(!e)return;let t=document.documentElement;function n(){return t.classList.contains("dark-mode")||!t.classList.contains("light-mode")&&window.matchMedia("(prefers-color-scheme: dark)").matches}function s(){e.textContent=n()?"\u2600\uFE0F Light":"\u{1F319} Dark"}s(),e.addEventListener("click",()=>{let i=n();t.classList.toggle("light-mode",i),t.classList.toggle("dark-mode",!i),$s(i?"light":"dark"),s()}),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{Is()||s()})}function Hs(){let e=_(".file_list_container").filter(n=>n.style.display!=="none"),t=e.length?R(".col-filter--name",e[0]):null;t&&t.focus()}function ks(e,t){Ye()?(e.preventDefault(),Le()):t?e.target.blur():Xe()&&re(null)}function Ds(e){e.key==="n"&&!e.shiftKey&&(e.preventDefault(),Je(1)),(e.key==="N"||e.key==="n"&&e.shiftKey||e.key==="p")&&(e.preventDefault(),Je(-1))}function Bs(e){e.key==="j"&&(e.preventDefault(),Ze(1)),e.key==="k"&&(e.preventDefault(),Ze(-1)),e.key==="Enter"&&Xe()&&(e.preventDefault(),Xt())}function tn(e){let t=e.target.matches("input, select, textarea");e.key==="/"&&!t?(e.preventDefault(),Hs()):e.key==="Escape"?ks(e,t):t||(Ye()?Ds(e):Bs(e))}function nn(){let e=1/0;_("abbr.timeago").forEach(t=>{let n=new Date(t.getAttribute("title")||"");Number.isNaN(n.getTime())||(t.textContent=dt(n),e=Math.min(e,ft(n)))}),e<1/0&&setTimeout(nn,e)}function Ps(){_(".file_list_container").forEach(e=>e.style.display="none"),_(".file_list_container").forEach(e=>{let t=e.id,n=e.querySelector(".group_name"),s=e.querySelector(".covered_percent"),i=document.createElement("li");i.setAttribute("role","tab");let c=document.createElement("a");c.href="#"+t,c.className=t,c.innerHTML=(n?n.innerHTML:"")+" ("+(s?s.innerHTML:"")+")",i.appendChild(c),document.querySelector(".group_tabs").appendChild(i)}),P(document.querySelector(".group_tabs"),"click","a",function(e){e.preventDefault(),window.location.hash=this.getAttribute("href").replace("#","#_")})}function Fs(e){e&&(e.style.transition="opacity 0.3s",e.style.opacity="0",setTimeout(()=>{e.style.display="none"},300));let t=document.getElementById("wrapper");t&&t.classList.remove("hide"),Ge()}function Us(){return J(this,null,function*(){let e=window.SIMPLECOV_DATA,t=document.getElementById("loading");t&&(t.style.display=""),yield pt(Object.keys(e.coverage)),Pt(e),nn(),en(),Wt(),Kt(),document.addEventListener("keydown",tn),Yt(),Qt(),Ps(),window.addEventListener("resize",ie),xe(),Fs(t)})}document.addEventListener("DOMContentLoaded",Us);})();
|
|
15
|
+
</div>`;let o=r-s,c=r>0?s*100/r:100,d=P(c),p=e.suffix||"covered",M=e.missedClass||"red",w=`<div class="t-${t}-summary">
|
|
16
|
+
${n}: <span class="${d}"><b>${U(c)}%</b></span><span class="coverage-cell__fraction"> ${s}/${r} ${p}</span>`;if(o>0){let A=i?`<a href="#" class="t-missed-method-toggle"><b>${o}</b> missed</a>`:`<span class="${M}"><b>${o}</b> missed</span>`;w+=`<span class="coverage-cell__fraction">,</span>
|
|
17
|
+
${A}`}return w+=`
|
|
18
|
+
</div>`,w}function qt(e){return'<div class="summary-stats">'+je({type:"line",label:"Line coverage",covered:e.coveredLines,total:e.totalLines,enabled:!0,suffix:"relevant lines covered"})+je({type:"branch",label:"Branch coverage",covered:e.coveredBranches,total:e.totalBranches,enabled:e.branchCoverage,missedClass:"missed-branch-text"})+je({type:"method",label:"Method coverage",covered:e.coveredMethods,total:e.totalMethods,enabled:e.methodCoverage,missedClass:"missed-method-text-color",toggle:e.showMethodToggle})+"</div>"}function xs(e){let{title:t,filenames:n,stats:s,branchCoverage:r,methodCoverage:l}=e,i=gt(t),o=s.lines,c=r?s.branches:void 0,d=l?s.methods:void 0,p=[`<div class="file_list_container" id="${i}" data-total-files="${n.length}">`,`<span class="group_name hide">${I(t)}</span>`,`<span class="covered_percent hide"><span class="${P(o.percent)}">${U(o.percent)}%</span></span>`,'<div class="file_list--responsive"><table class="file_list"><thead><tr>','<th class="cell--left"><div class="th-with-filter"><span class="th-label">File Name</span><input type="search" class="col-filter col-filter--name" placeholder="Filter paths\u2026"></div></th>',Se("Line Coverage","line","Covered","Lines")];r&&p.push(Se("Branch Coverage","branch","Covered","Branches")),l&&p.push(Se("Method Coverage","method","Covered","Methods")),p.push("</tr>");let M=n.length===1?"file":"files";return p.push(`<tr class="totals-row"><td class="strong t-file-count">${x(n.length)} ${M}</td>`,Y(o.percent,o.covered,o.total,"line",!0)),c&&p.push(Y(c.percent,c.covered,c.total,"branch",!0)),d&&p.push(Y(d.percent,d.covered,d.total,"method",!0)),p.push("</tr></thead><tbody>"),p.join("")}function As(e){let{filename:t,coverage:n,branchCoverage:s,methodCoverage:r}=e,l=ee(t),i=[`data-covered-lines="${n.covered_lines}"`,`data-relevant-lines="${n.total_lines}"`];s&&i.push(`data-covered-branches="${n.covered_branches||0}"`,`data-total-branches="${n.total_branches||0}"`),r&&i.push(`data-covered-methods="${n.covered_methods||0}"`,`data-total-methods="${n.total_methods||0}"`);let o=[`<tr class="t-file" ${i.join(" ")}>`,`<td class="strong t-file__name"><a href="#${l}" class="src_link" title="${I(t)}">${I(t)}</a></td>`,Y(n.lines_covered_percent,n.covered_lines,n.total_lines,"line",!1)];if(s){let c=n.branches_covered_percent===void 0?100:n.branches_covered_percent;o.push(Y(c,n.covered_branches||0,n.total_branches||0,"branch",!1))}if(r){let c=n.methods_covered_percent===void 0?100:n.methods_covered_percent;o.push(Y(c,n.covered_methods||0,n.total_methods||0,"method",!1))}return o.push("</tr>"),o.join("")}function Ge(e){let{filenames:t,allCoverage:n,branchCoverage:s,methodCoverage:r}=e,l=[xs(e)];for(let i of t){let o=n[i];o&&l.push(As({filename:i,coverage:o,branchCoverage:s,methodCoverage:r}))}return l.push("</tbody></table></div></div>"),l.join("")}function Cs(e){let{lineIndex:t,lineCov:n,branchesReport:s,missedMethodLines:r,branchCoverage:l,methodCoverage:i}=e,o=t+1;if(n==="ignored")return"skipped";if(l){let c=s[o];if(c&&c.some(([,d])=>d===0))return"missed-branch"}return i&&r.has(o)?"missed-method":n===null?"never":n===0?"missed":"covered"}function Rs(e){let t={};if(!e)return t;for(let{coverage:n,report_line:s,type:r}of e){if(n==="ignored")continue;(t[s]||(t[s]=[])).push([r,n])}return t}function Ns(e){let t=new Set;if(!e)return t;for(let n of e)if(n.coverage===0&&n.start_line&&n.end_line)for(let s=n.start_line;s<=n.end_line;s++)t.add(s);return t}function Os(e){let{index:t,source:n,lineCov:s,status:r,branchCoverage:l,lineBranches:i}=e,o=t+1,c=s!==null&&s!=="ignored"?` data-hits="${s}"`:"",d=[`<li class="${r}"${c} data-linenumber="${o}">`];if(r==="covered"||s!==null&&s!=="ignored"&&s!==0?d.push(`<span class="hits" data-content="${s}"></span>`):s==="ignored"&&d.push('<span class="hits" data-content="skipped"></span>'),l&&i)for(let[p,M]of i){let w=I(p);d.push(`<span class="hits" data-content="${w}: ${M}" title="${w} branch hit ${M} times"></span>`)}return d.push(`<code class="ruby">${I(n)}</code></li>`),d.join("")}function Wt(e,t,n,s){let r=ee(e),l=t.covered_lines,i=t.total_lines,o=n&&t.covered_branches||0,c=n&&t.total_branches||0,d=s&&t.covered_methods||0,p=s&&t.total_methods||0,M=(t.methods||[]).filter(N=>N.coverage===0),w=s&&M.length>0,A=Rs(t.branches),$=Ns(t.methods),C=[`<div class="source_table" id="${r}">`,'<div class="header">',`<h2>${I(e)}</h2>`,qt({coveredLines:l,totalLines:i,coveredBranches:o,totalBranches:c,coveredMethods:d,totalMethods:p,branchCoverage:n,methodCoverage:s,showMethodToggle:w})];w&&C.push('<div class="t-missed-method-list" style="display: none"><ul>',M.map(N=>`<li><tt>${I(N.name)}</tt></li>`).join(""),"</ul></div>"),C.push("</div>","<pre><ol>");for(let N=0;N<t.source.length;N++){let le=t.lines[N],pe=Cs({lineIndex:N,lineCov:le,branchesReport:A,missedMethodLines:$,branchCoverage:n,methodCoverage:s});C.push(Os({index:N,source:t.source[N],lineCov:le,status:pe,branchCoverage:n,lineBranches:n?A[N+1]:void 0}))}return C.push("</ol></pre></div>"),C.join("")}Ue.registerLanguage("ruby",Pt);var se=null;function Ut(e){let t=e.meta,n=t.branch_coverage,s=t.method_coverage;document.title=`Code coverage for ${t.project_name}`;let r=Object.keys(e.coverage),l=e.total.lines.total>0?e.total.lines.percent:100,i=document.createElement("link");i.rel="icon",i.type="image/png",i.href=`favicon_${P(l)}.png`,document.head.appendChild(i),n&&document.body.setAttribute("data-branch-coverage","true");let o=document.getElementById("content"),c=[Ge({title:"All Files",filenames:r,stats:e.total,allCoverage:e.coverage,branchCoverage:n,methodCoverage:s})];for(let $ of Object.keys(e.groups)){let C=e.groups[$];c.push(Ge({title:$,filenames:C.files||[],stats:C,allCoverage:e.coverage,branchCoverage:n,methodCoverage:s}))}o.innerHTML=c.join("");let d={};for(let $ of r)d[ee($)]=$;se={idToFilename:d,coverage:e.coverage,branchCoverage:n,methodCoverage:s};let p=new Date(t.timestamp),M=document.getElementById("footer");M.innerHTML=`Generated <abbr class="timeago" title="${p.toISOString()}">${p.toISOString()}</abbr> by <a href="https://github.com/simplecov-ruby/simplecov">simplecov</a> v${I(t.simplecov_version)} using ${I(t.command_name)}`;let w=document.getElementById("source-legend"),A='<span class="source-legend__item"><span class="source-legend__swatch source-legend__swatch--covered"></span>Covered</span><span class="source-legend__item"><span class="source-legend__swatch source-legend__swatch--skipped"></span>Skipped</span><span class="source-legend__item"><span class="source-legend__swatch source-legend__swatch--missed"></span>Missed line</span>';n&&(A+='<span class="source-legend__item"><span class="source-legend__swatch source-legend__swatch--missed-branch"></span>Missed branch</span>'),s&&(A+='<span class="source-legend__item"><span class="source-legend__swatch source-legend__swatch--missed-method"></span>Missed method</span>'),w.innerHTML=A}function jt(e){let t=document.getElementById(e);if(t)return t;if(!se)return null;let n=se.idToFilename[e];if(!n)return null;let s=Wt(n,se.coverage[n],se.branchCoverage,se.methodCoverage),r=document.querySelector(".source_files"),l=document.createElement("div");l.innerHTML=s;let i=l.firstElementChild;return r.appendChild(i),E("pre code",i).forEach(o=>Ue.highlightElement(o)),i}var Ke=1e3,Is="t-window-hidden",zt=new WeakSet;function Hs(e,t){let n=e.querySelector("tr.t-show-all");if(!n){n=document.createElement("tr"),n.className="t-show-all";let s=document.createElement("td");s.colSpan=t,n.appendChild(s),n.addEventListener("click",r=>{r.preventDefault(),zt.add(e),re(e.closest("table"))}),e.appendChild(n)}return n}function re(e){let t=e.querySelector("tbody");if(!t)return;let n=t.querySelectorAll("tr.t-file"),s=zt.has(t),r=0;if(n.forEach(i=>{let o=i.style.display==="none";o||(r+=1),i.classList.toggle(Is,!s&&!o&&r>Ke)}),s||r<=Ke){let i=t.querySelector("tr.t-show-all");i&&(i.style.display="none");return}let l=Hs(t,n[0].children.length);l.style.display="",l.firstElementChild.innerHTML=`Showing the first ${x(Ke)} of ${x(r)} files. <a href="#" class="t-show-all__link">Show all</a>`,t.appendChild(l)}var Xt={};function $s(e,t){let n=0,s=e.children;for(let r=0;r<s.length;r++)if(s[r].style.display!=="none"){if(n===t)return r;n+=1}return null}function ks(e){if(!e)return"";let t=e.getAttribute("data-order");if(t!==null)return Number.parseFloat(t);let n=(e.textContent||"").trim(),s=Number.parseFloat(n);return Number.isNaN(s)?n.toLowerCase():s}var Gt=new WeakMap;function Vt(e,t){var l;if(t===null)return"";let n=Gt.get(e);n||(n=new Map,Gt.set(e,n));let s=n.get(t);if(s!==void 0)return s;let r=ks((l=e.children[t])!=null?l:null);return n.set(t,r),r}var Ds=new Intl.Collator;function Zt(e,t){return typeof e=="number"&&typeof t=="number"?e-t:Ds.compare(String(e),String(t))}function Yt(e){return e.id||e.getAttribute("data-sort-id")||"default"}function Xe(e,t,n){Xt[Yt(e)]={colIndex:t,direction:n};let s=0;E("thead tr:first-child th",e).forEach(r=>{let l=Number.parseInt(r.getAttribute("colspan")||"1",10);r.classList.remove("sorting_asc","sorting_desc","sorting");let i=t>=s&&t<s+l;r.classList.add(i?n==="asc"?"sorting_asc":"sorting_desc":"sorting"),s+=l})}function Qt(e,t){let n=document.createDocumentFragment();t.forEach(s=>n.appendChild(s)),e.appendChild(n)}function Kt(e,t){let n=Xt[Yt(e)],s=n&&n.colIndex===t&&n.direction==="asc"?"desc":"asc",r=e.querySelector("tbody"),l=Array.from(r.querySelectorAll("tr.t-file"));if(l.length===0){Xe(e,t,s);return}if(n&&n.colIndex===t)l.reverse();else{let i=$s(l[0],t),o=l.map(d=>({row:d,value:Vt(d,i)})),c=s==="asc"?1:-1;o.sort((d,p)=>c*Zt(d.value,p.value)),l=o.map(({row:d})=>d)}Qt(r,l),re(e),Xe(e,t,s)}var Bs=500,de=null;function Fs(){if(de)return de;let e=document.createElement("div");return e.id="sort-overlay",e.innerHTML='<span id="sort-overlay-label">Sorting\u2026</span>',e.style.display="none",document.body.appendChild(e),de=e,e}function Ps(){let e=Fs();e.style.transition="none",e.style.opacity="1",e.style.display="flex"}function qs(){if(!de)return;let e=de;e.style.transition="opacity 0.15s",e.style.opacity="0",setTimeout(()=>{e.style.display="none"},150)}function Ws(e,t){if(e.querySelectorAll("tbody tr.t-file").length<Bs){Kt(e,t);return}Ps(),requestAnimationFrame(()=>requestAnimationFrame(()=>{Kt(e,t),qs()}))}function Us(e,t){let n=0;for(let s of E("thead tr:first-child th",e)){let r=Number.parseInt(s.getAttribute("colspan")||"1",10);if(s===t)return n+r-1;n+=r}return n}function js(e,t){let n=Array.from(e.children);if(t){let r=n.findIndex(l=>l.classList.contains(`cell--${t}-pct`));if(r!==-1)return r}let s=n.findIndex(r=>r.hasAttribute("data-order"));return s===-1?null:s}function zs(e,t){let n=e.querySelector("tbody");if(!n)return;let s=Array.from(n.querySelectorAll("tr.t-file"));if(s.length===0)return;let r=js(s[0],t);if(r===null)return;let l=s.map(i=>({row:i,value:Vt(i,r)}));l.sort((i,o)=>Zt(i.value,o.value)),Qt(n,l.map(({row:i})=>i)),Xe(e,r,"asc")}function Jt(e){E("table.file_list").forEach(t=>{E("thead tr:first-child th",t).forEach(n=>{n.classList.add("sorting"),n.style.cursor="pointer",n.addEventListener("click",()=>Ws(t,Us(t,n)))}),zs(t,e),re(t)})}var fe=null;function Te(){fe=null}function en(){if(fe)return fe;let e=E(".file_list_container").filter(t=>t.style.display!=="none");return e.length?(fe=E("tbody tr.t-file",e[0]).filter(t=>t.style.display!=="none"),fe):[]}var Gs=240,Ks=160;function tn(e,t){e.style.setProperty("--bar-sizer-width",t+"px")}function Ze(){E(".file_list_container").forEach(e=>{if(e.style.display==="none"||e.offsetWidth===0)return;let t=R("table.file_list",e);if(!t||!R(".bar-sizer",t))return;let n=t.closest(".file_list--responsive");if(!n)return;n.style.visibility="hidden";let s=Ks,r=Gs;for(;s<r;){let l=Math.ceil((s+r)/2);tn(t,l),t.offsetWidth,t.scrollWidth<=n.clientWidth?s=l:r=l-1}tn(t,s),n.style.visibility=""})}var Ve=0;function ie(){Ve||(Ve=requestAnimationFrame(()=>{Ve=0,Ze()}))}var Le={line:{covered:"coveredLines",total:"relevantLines"},branch:{covered:"coveredBranches",total:"totalBranches"},method:{covered:"coveredMethods",total:"totalMethods"}};function nn(e){let t=E("tbody tr.t-file",e).filter(l=>l.style.display!=="none");function n(l){return t.reduce((i,o)=>i+(Number.parseInt(o.dataset[l]||"0",10)||0),0)}let s=R(".t-file-count",e),r=Number.parseInt(e.getAttribute("data-total-files")||"0",10);if(s){let l=t.length===1?" file":" files";s.textContent=t.length===r?x(r)+l:x(t.length)+"/"+x(r)+l}for(let l of Object.keys(Le)){let i=Le[l],o=`.t-totals__${l}`;R(o+"-pct",e)&&Xs(e,o,n(i.covered),n(i.total))}}function Xs(e,t,n,s){let r=R(t+"-pct",e),l=R(t+"-num",e),i=R(t+"-den",e);if(s===0){r&&(r.innerHTML="",r.classList.remove("green","yellow","red")),l&&(l.textContent=""),i&&(i.textContent="");return}let o=n*100/s,c=P(o);r&&(r.innerHTML=`<div class="coverage-cell">${ze(o)}<span class="coverage-pct">${U(o)}%</span></div>`,r.classList.remove("green","yellow","red"),r.classList.add(c)),l&&(l.textContent=x(n)+"/"),i&&(i.textContent=x(s))}var Vs={gt:(e,t)=>e>t,gte:(e,t)=>e>=t,eq:(e,t)=>e===t,lte:(e,t)=>e<=t,lt:(e,t)=>e<t};function Zs(e,t,n){let s=Vs[e];return s?s(t,n):!0}function Ys(e){let t=[];for(let n of E(".col-filter__value",e)){let s=n;if(!s.value)continue;let r=Number.parseFloat(s.value);if(Number.isNaN(r))continue;let l=s.dataset.type||"",i=R(`.col-filter__op[data-type="${l}"]`,e),o=i?i.value:"",c=Le[l];o&&c&&t.push({attrs:c,op:o,threshold:r})}return t}var sn=new WeakMap;function Qs(e){let t=sn.get(e);return t===void 0&&(t=(e.children[0].textContent||"").toLowerCase(),sn.set(e,t)),t}function rn(e){let t=R("table.file_list",e);if(!t)return;let n=R(".col-filter--name",e),s=n?n.value.trim().toLowerCase():"",r=Ys(e);E("tbody tr.t-file",t).forEach(l=>{let i=l,c=(!s||Qs(l).includes(s))&&r.every(d=>{let p=Number.parseInt(i.dataset[d.attrs.covered]||"0",10)||0,M=Number.parseInt(i.dataset[d.attrs.total]||"0",10)||0,w=M>0?p*100/M:100;return Zs(d.op,w,d.threshold)})?"":"none";i.style.display!==c&&(i.style.display=c)}),re(t),Te(),nn(e),ie()}function Ye(e){let t=Number.parseFloat(e.value),n=e.closest(".col-filter__coverage"),s=n?n.querySelector(".col-filter__op"):null;if(!s)return;let r=s.querySelector('option[value="gt"]'),l=s.querySelector('option[value="lt"]');if(r&&(r.disabled=t>=100),l&&(l.disabled=t<=0),s.selectedOptions[0]&&s.selectedOptions[0].disabled){let i=s.querySelector("option:not(:disabled)");i&&(s.value=i.value)}}function on(){E(".col-filter__value").forEach(e=>Ye(e)),E(".col-filter--name, .col-filter__op, .col-filter__value, .col-filter__coverage").forEach(e=>{e.addEventListener("click",t=>t.stopPropagation())}),F(document,"input",".col-filter--name, .col-filter__op, .col-filter__value",function(){this.classList.contains("col-filter__value")&&Ye(this),rn(this.closest(".file_list_container"))}),F(document,"change",".col-filter__op, .col-filter__value",function(){this.classList.contains("col-filter__value")&&Ye(this),rn(this.closest(".file_list_container"))})}var H=null;function Qe(){return H!==null}function oe(e){H&&H.classList.remove("keyboard-focus"),H=e,H&&(H.classList.add("keyboard-focus"),H.scrollIntoView({block:"nearest"}))}function Je(e){let t=en();if(!t.length)return;if(!H||t.indexOf(H)===-1){oe(e===1?t[0]:t[t.length-1]);return}let n=t.indexOf(H)+e;n>=0&&n<t.length&&oe(t[n])}function ln(){if(!H)return;let e=H.querySelector("a.src_link");e&&(window.location.hash=e.getAttribute("href").substring(1))}var j,Q,et,ge=null,xe="";function tt(){return j.open}function nt(){return Q}function an(){if(!ge)return;xe&&(ge.insertAdjacentHTML("afterbegin",xe),xe="");let e=document.querySelector(".source_files");e&&e.appendChild(ge),ge=null}function Js(e,t){an();let n=jt(e);if(!n)return;let s=n.querySelector(".header");if(s&&(xe=s.outerHTML,et.innerHTML=s.innerHTML,s.remove()),ge=n,Q.appendChild(n),j.open||j.showModal(),document.documentElement.style.overflow="hidden",Q.focus(),t){let r=Q.querySelector('li[data-linenumber="'+t+'"]');r&&(Q.scrollTop=r.offsetTop)}}function cn(e){if(oe(null),Te(),j.open&&(an(),j.close(),Q.innerHTML="",et.innerHTML="",document.documentElement.style.overflow=""),e){let n=document.querySelector(".group_tabs a."+e);if(n){E(".group_tabs li").forEach(r=>r.classList.remove("active")),n.parentElement.classList.add("active"),E(".file_list_container").forEach(r=>r.style.display="none");let s=document.getElementById(e);s&&(s.style.display="")}}let t=document.getElementById("wrapper");t&&!t.classList.contains("hide")&&ie()}function Ce(){let e=window.location.hash.substring(1);if(!e){let t=document.querySelector(".group_tabs a");t&&cn(t.getAttribute("href").replace("#",""));return}if(e.charAt(0)==="_")cn(e.substring(1));else{let t=e.split("-L");if(!document.querySelector(".group_tabs li.active")){let n=document.querySelector(".group_tabs li");n&&n.classList.add("active")}Js(t[0],t[1])}}function Ae(){let e=document.querySelector(".group_tabs li.active a");e&&(window.location.hash=e.getAttribute("href").replace("#","#_"))}function un(){j=document.getElementById("source-dialog"),Q=document.getElementById("source-dialog-body"),et=document.getElementById("source-dialog-title"),j.querySelector(".source-dialog__close").addEventListener("click",Ae),j.addEventListener("click",e=>{e.target===j&&Ae()})}function er(){return E(".source-dialog .source_table li.missed, .source-dialog .source_table li.missed-branch, .source-dialog .source_table li.missed-method")}function st(e){let t=er();if(!t.length)return;let n=nt(),s=n.scrollTop+n.clientHeight/2,r=e===1?t.find(l=>l.offsetTop>s)||t[0]:t.findLast(l=>l.offsetTop<s-10)||t[t.length-1];n.scrollTop=r.offsetTop-n.clientHeight/3}function dn(){F(document,"click",".t-missed-method-toggle",function(e){e.preventDefault();let t=this.closest(".header")||this.closest(".source-dialog__title")||this.closest(".source-dialog__header"),n=t?t.querySelector(".t-missed-method-list"):null;n&&(n.style.display=n.style.display==="none"?"":"none")}),F(document,"click","a.src_link",function(e){e.preventDefault(),window.location.hash=this.getAttribute("href").substring(1)}),F(document,"click","table.file_list tbody tr",function(e){if(e.target.closest("a"))return;let t=this.querySelector("a.src_link");t&&(window.location.hash=t.getAttribute("href").substring(1))}),F(document,"click",".source-dialog .source_table li[data-linenumber]",function(e){e.preventDefault(),nt().scrollTop=this.offsetTop;let t=this.dataset.linenumber,n=window.location.hash.substring(1).replace(/-L.*/,"");window.location.replace(window.location.href.replace(/#.*/,"#"+n+"-L"+t))}),window.addEventListener("hashchange",Ce)}var fn="simplecov-dark-mode";function tr(){try{return localStorage.getItem(fn)}catch(e){return null}}function nr(e){try{localStorage.setItem(fn,e)}catch(t){}}function gn(){let e=document.getElementById("dark-mode-toggle");if(!e)return;let t=document.documentElement;function n(){return t.classList.contains("dark-mode")||!t.classList.contains("light-mode")&&window.matchMedia("(prefers-color-scheme: dark)").matches}function s(){e.textContent=n()?"\u2600\uFE0F Light":"\u{1F319} Dark"}s(),e.addEventListener("click",()=>{let r=n();t.classList.toggle("light-mode",r),t.classList.toggle("dark-mode",!r),nr(r?"light":"dark"),s()}),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{tr()||s()})}function sr(){let e=E(".file_list_container").filter(n=>n.style.display!=="none"),t=e.length?R(".col-filter--name",e[0]):null;t&&t.focus()}function rr(e,t){tt()?(e.preventDefault(),Ae()):t?e.target.blur():Qe()&&oe(null)}function ir(e){e.key==="n"&&!e.shiftKey&&(e.preventDefault(),st(1)),(e.key==="N"||e.key==="n"&&e.shiftKey||e.key==="p")&&(e.preventDefault(),st(-1))}function or(e){e.key==="j"&&(e.preventDefault(),Je(1)),e.key==="k"&&(e.preventDefault(),Je(-1)),e.key==="Enter"&&Qe()&&(e.preventDefault(),ln())}function pn(e){let t=e.target.matches("input, select, textarea");e.key==="/"&&!t?(e.preventDefault(),sr()):e.key==="Escape"?rr(e,t):t||(tt()?ir(e):or(e))}function hn(){let e=1/0;E("abbr.timeago").forEach(t=>{let n=new Date(t.getAttribute("title")||"");Number.isNaN(n.getTime())||(t.textContent=ht(n),e=Math.min(e,mt(n)))}),e<1/0&&setTimeout(hn,e)}function lr(){E(".file_list_container").forEach(e=>e.style.display="none"),E(".file_list_container").forEach(e=>{let t=e.id,n=e.querySelector(".group_name"),s=e.querySelector(".covered_percent"),r=document.createElement("li");r.setAttribute("role","tab");let l=document.createElement("a");l.href="#"+t,l.className=t,l.innerHTML=(n?n.innerHTML:"")+" ("+(s?s.innerHTML:"")+")",r.appendChild(l),document.querySelector(".group_tabs").appendChild(r)}),F(document.querySelector(".group_tabs"),"click","a",function(e){e.preventDefault(),window.location.hash=this.getAttribute("href").replace("#","#_")})}function cr(e){e&&(e.style.transition="opacity 0.3s",e.style.opacity="0",setTimeout(()=>{e.style.display="none"},300));let t=document.getElementById("wrapper");t&&t.classList.remove("hide"),Ze()}function ar(){return J(this,null,function*(){let e=window.SIMPLECOV_DATA,t=document.getElementById("loading");t&&(t.style.display=""),yield Et(Object.keys(e.coverage)),Ut(e),hn(),gn(),Jt(e.meta.primary_coverage),on(),document.addEventListener("keydown",pn),un(),dn(),lr(),window.addEventListener("resize",ie),Ce(),cr(t)})}document.addEventListener("DOMContentLoaded",ar);})();
|
|
@@ -61,7 +61,8 @@ module SimpleCov
|
|
|
61
61
|
project_name: SimpleCov.project_name,
|
|
62
62
|
timestamp: @result.created_at.iso8601(3),
|
|
63
63
|
root: SimpleCov.root,
|
|
64
|
-
commit: git_commit
|
|
64
|
+
commit: git_commit,
|
|
65
|
+
primary_coverage: SimpleCov.primary_coverage.to_s
|
|
65
66
|
}.merge!(coverage_flags)
|
|
66
67
|
end
|
|
67
68
|
|
|
@@ -39,6 +39,16 @@ module SimpleCov
|
|
|
39
39
|
# No-op default; polling fallback handles correctness.
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
+
# Does `wait_for_siblings` block until every sibling PROCESS has
|
|
43
|
+
# exited (so no further resultset can appear)? When true, the
|
|
44
|
+
# reporting worker can accept a settled resultset count below
|
|
45
|
+
# `expected_worker_count` as final instead of waiting out the whole
|
|
46
|
+
# `parallel_wait_timeout` for workers that produced no coverage.
|
|
47
|
+
# Defaults to false (no native wait; the poll is the only signal).
|
|
48
|
+
def native_wait?
|
|
49
|
+
false
|
|
50
|
+
end
|
|
51
|
+
|
|
42
52
|
# How many parallel workers are participating in this run. Used
|
|
43
53
|
# by the polling fallback to know how many resultset entries to
|
|
44
54
|
# expect. Defaults to 1 (single-process).
|
|
@@ -43,6 +43,12 @@ module SimpleCov
|
|
|
43
43
|
::ParallelTests.wait_for_other_processes_to_finish
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
+
# The native wait blocks until every sibling process exits, but only
|
|
47
|
+
# when the pid-file contract is present (see `wait_for_siblings`).
|
|
48
|
+
def native_wait?
|
|
49
|
+
native_parallel_tests_environment?
|
|
50
|
+
end
|
|
51
|
+
|
|
46
52
|
def expected_worker_count
|
|
47
53
|
ENV["PARALLEL_TEST_GROUPS"]&.to_i || 1
|
|
48
54
|
end
|
|
@@ -39,7 +39,8 @@ module SimpleCov
|
|
|
39
39
|
# expected workers have reported or a timeout is reached. Capture
|
|
40
40
|
# the outcome so `ready_to_process_results?` can suppress min/max
|
|
41
41
|
# threshold checks against a partial total.
|
|
42
|
-
@parallel_results_complete =
|
|
42
|
+
@parallel_results_complete =
|
|
43
|
+
wait_for_parallel_results(adapter.expected_worker_count, native_wait: adapter.native_wait?)
|
|
43
44
|
end
|
|
44
45
|
|
|
45
46
|
# @api private — true when every sibling reported its resultset
|
|
@@ -49,28 +50,63 @@ module SimpleCov
|
|
|
49
50
|
defined?(@parallel_results_complete) ? @parallel_results_complete : true
|
|
50
51
|
end
|
|
51
52
|
|
|
52
|
-
# @api private —
|
|
53
|
-
# before
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
# @api private — seconds the resultset count must hold steady, after a
|
|
54
|
+
# native wait, before we accept fewer than `expected` workers as final.
|
|
55
|
+
PARALLEL_RESULTS_SETTLE = 0.5
|
|
56
|
+
private_constant :PARALLEL_RESULTS_SETTLE
|
|
57
|
+
|
|
58
|
+
# @api private — returns true when the reporting worker has every
|
|
59
|
+
# resultset it's going to get, false on timeout. Single-process runs
|
|
60
|
+
# (expected <= 1) short-circuit to true with no waiting.
|
|
61
|
+
#
|
|
62
|
+
# Normally we poll until `expected` (= PARALLEL_TEST_GROUPS) workers have
|
|
63
|
+
# reported or `SimpleCov.parallel_wait_timeout` elapses; raise that setting
|
|
56
64
|
# when a slow worker routinely finishes well after the others.
|
|
57
|
-
|
|
65
|
+
#
|
|
66
|
+
# When a native wait already confirmed every sibling PROCESS exited
|
|
67
|
+
# (`native_wait`), no further resultset will appear, so a count below
|
|
68
|
+
# `expected` just means some workers produced none — e.g. parallel_test
|
|
69
|
+
# groups that got no spec file on a machine with more cores than files.
|
|
70
|
+
# Once the count then holds steady for `PARALLEL_RESULTS_SETTLE` we accept
|
|
71
|
+
# it as final rather than blocking for the whole timeout. Without a native
|
|
72
|
+
# wait (GenericAdapter) we can't tell an idle worker from a slow one, so we
|
|
73
|
+
# keep waiting the full timeout.
|
|
74
|
+
def wait_for_parallel_results(expected, native_wait: false)
|
|
58
75
|
return true unless expected > 1 # simplecov:disable branch — only false in real parallel runs
|
|
59
76
|
|
|
60
|
-
deadline =
|
|
77
|
+
deadline = monotonic_time + parallel_wait_timeout
|
|
78
|
+
tracker = {count: 0, since: monotonic_time}
|
|
61
79
|
loop do
|
|
62
80
|
seen = SimpleCov::ResultMerger.read_resultset.size
|
|
63
81
|
return true if seen >= expected
|
|
82
|
+
return true if native_wait && resultset_count_settled?(tracker, seen)
|
|
64
83
|
return false if parallel_wait_timed_out?(deadline, expected, seen)
|
|
65
84
|
|
|
66
85
|
sleep 0.1
|
|
67
86
|
end
|
|
68
87
|
end
|
|
69
88
|
|
|
89
|
+
# Track whether the resultset count has held steady (and positive) for
|
|
90
|
+
# `PARALLEL_RESULTS_SETTLE` seconds. `tracker` carries the last count and
|
|
91
|
+
# the time it last changed across poll iterations.
|
|
92
|
+
def resultset_count_settled?(tracker, count)
|
|
93
|
+
if count > tracker[:count]
|
|
94
|
+
tracker[:count] = count
|
|
95
|
+
tracker[:since] = monotonic_time
|
|
96
|
+
return false
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
count.positive? && (monotonic_time - tracker[:since]) >= PARALLEL_RESULTS_SETTLE
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def monotonic_time
|
|
103
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
104
|
+
end
|
|
105
|
+
|
|
70
106
|
# @api private — true once the wait deadline has passed; warns on
|
|
71
107
|
# the first timeout so the user knows the merged total is partial.
|
|
72
108
|
def parallel_wait_timed_out?(deadline, expected, seen)
|
|
73
|
-
return false unless
|
|
109
|
+
return false unless monotonic_time > deadline
|
|
74
110
|
|
|
75
111
|
warn_about_incomplete_parallel_results(expected, seen)
|
|
76
112
|
true
|
data/lib/simplecov/version.rb
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"timestamp",
|
|
23
23
|
"root",
|
|
24
24
|
"commit",
|
|
25
|
+
"primary_coverage",
|
|
25
26
|
"line_coverage",
|
|
26
27
|
"branch_coverage",
|
|
27
28
|
"method_coverage"
|
|
@@ -52,6 +53,11 @@
|
|
|
52
53
|
"type": ["string", "null"],
|
|
53
54
|
"description": "Full git commit SHA of `root`'s HEAD when the report was generated, or null when the project isn't a git checkout (or git isn't available). Lets tools recover the exact source a report reflects, which matters most when `source_in_json` is false and the per-file `source` arrays are omitted."
|
|
54
55
|
},
|
|
56
|
+
"primary_coverage": {
|
|
57
|
+
"type": "string",
|
|
58
|
+
"enum": ["line", "branch", "method"],
|
|
59
|
+
"description": "The coverage criterion `SimpleCov.primary_coverage` names as primary. The HTML report sorts file lists by this criterion's coverage by default."
|
|
60
|
+
},
|
|
55
61
|
"line_coverage": {"type": "boolean"},
|
|
56
62
|
"branch_coverage": {"type": "boolean"},
|
|
57
63
|
"method_coverage": {"type": "boolean"}
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"timestamp",
|
|
23
23
|
"root",
|
|
24
24
|
"commit",
|
|
25
|
+
"primary_coverage",
|
|
25
26
|
"line_coverage",
|
|
26
27
|
"branch_coverage",
|
|
27
28
|
"method_coverage"
|
|
@@ -52,6 +53,11 @@
|
|
|
52
53
|
"type": ["string", "null"],
|
|
53
54
|
"description": "Full git commit SHA of `root`'s HEAD when the report was generated, or null when the project isn't a git checkout (or git isn't available). Lets tools recover the exact source a report reflects, which matters most when `source_in_json` is false and the per-file `source` arrays are omitted."
|
|
54
55
|
},
|
|
56
|
+
"primary_coverage": {
|
|
57
|
+
"type": "string",
|
|
58
|
+
"enum": ["line", "branch", "method"],
|
|
59
|
+
"description": "The coverage criterion `SimpleCov.primary_coverage` names as primary. The HTML report sorts file lists by this criterion's coverage by default."
|
|
60
|
+
},
|
|
55
61
|
"line_coverage": {"type": "boolean"},
|
|
56
62
|
"branch_coverage": {"type": "boolean"},
|
|
57
63
|
"method_coverage": {"type": "boolean"}
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: simplecov
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.0.
|
|
4
|
+
version: 1.0.0.rc5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Erik Berlin
|
|
@@ -30,7 +30,6 @@ executables:
|
|
|
30
30
|
extensions: []
|
|
31
31
|
extra_rdoc_files: []
|
|
32
32
|
files:
|
|
33
|
-
- CHANGELOG.md
|
|
34
33
|
- LICENSE
|
|
35
34
|
- README.md
|
|
36
35
|
- doc/alternate-formatters.md
|
|
@@ -151,9 +150,9 @@ licenses:
|
|
|
151
150
|
metadata:
|
|
152
151
|
bug_tracker_uri: https://github.com/simplecov-ruby/simplecov/issues
|
|
153
152
|
changelog_uri: https://github.com/simplecov-ruby/simplecov/blob/main/CHANGELOG.md
|
|
154
|
-
documentation_uri: https://www.rubydoc.info/gems/simplecov/1.0.0.
|
|
153
|
+
documentation_uri: https://www.rubydoc.info/gems/simplecov/1.0.0.rc5
|
|
155
154
|
mailing_list_uri: https://groups.google.com/forum/#!forum/simplecov
|
|
156
|
-
source_code_uri: https://github.com/simplecov-ruby/simplecov/tree/v1.0.0.
|
|
155
|
+
source_code_uri: https://github.com/simplecov-ruby/simplecov/tree/v1.0.0.rc5
|
|
157
156
|
rubygems_mfa_required: 'true'
|
|
158
157
|
rdoc_options: []
|
|
159
158
|
require_paths:
|
data/CHANGELOG.md
DELETED
|
@@ -1,305 +0,0 @@
|
|
|
1
|
-
1.0.0.rc4 (2026-06-26)
|
|
2
|
-
======================
|
|
3
|
-
|
|
4
|
-
## Enhancements
|
|
5
|
-
* Added `SimpleCov.finalize_merge` to separate storing mergeable worker resultsets from owning final report finalization. Parallel workers that write to explicit custom coverage destinations can now store their shard `.resultset.json` files without waiting on sibling shards they cannot see; an explicit `SimpleCov.collate` cleanup step then formats the merged report, enforces thresholds, and writes `.last_run.json`. SimpleCov infers this external-finalization mode only for recognized multi-worker parallel runs with merging enabled and a custom coverage destination, and emits a configuration warning until users set `finalize_merge false` (or `true`) explicitly. See #1215.
|
|
6
|
-
|
|
7
|
-
## Bugfixes
|
|
8
|
-
* The `parallel_tests` adapter now only activates and uses the native wait API when the native pid-file synchronization contract is present. Processes that inherit `TEST_ENV_NUMBER` / `PARALLEL_TEST_GROUPS` without `PARALLEL_PID_FILE`, or lose `PARALLEL_PID_FILE` before SimpleCov's `at_exit` hook runs, now use the generic resultset polling path instead of calling `ParallelTests.wait_for_other_processes_to_finish` and failing when `parallel_tests` fetches the missing pid-file path. See #1210.
|
|
9
|
-
* The default `at_exit` formatter now writes reports only from the final parallel-test worker while still storing each worker's resultset for the final merge, so JSON/XML/HTML formatters no longer clobber canonical coverage files from non-final workers. See #1210.
|
|
10
|
-
* `SimpleCov.parallel_tests false` now disables the generic `TEST_ENV_NUMBER` adapter as well as the `parallel_tests` gem adapter, so projects that use those environment variables for a different coverage collation flow can opt out consistently. See #1208.
|
|
11
|
-
* Parallel result coordination now stores the final worker's own resultset before waiting for sibling resultsets, preventing an off-by-one timeout where the final worker reported `N-1` of `N` workers and skipped threshold checks immediately before producing a complete merged report. See #1208.
|
|
12
|
-
* Static branch coverage now matches Ruby's runtime branch tuple identities for `unless` and safe-navigation calls, and resultset merges now combine serialized branch tuples by source location instead of by their local sequential ids. This prevents equivalent branches from being duplicated when static and runtime branch extraction assign different ids. See #1206.
|
|
13
|
-
|
|
14
|
-
1.0.0.rc3 (2026-06-18)
|
|
15
|
-
======================
|
|
16
|
-
|
|
17
|
-
## Breaking Changes
|
|
18
|
-
* Dropped support for Ruby 3.1 and JRuby 9.4. The minimum is now Ruby 3.2 (and JRuby 10, which reports `RUBY_VERSION` 3.4). Ruby 3.1 reached end of life in March 2025, and a recent `i18n` release calls `Fiber[]`, a Ruby 3.2 API, at load time, so suites that load Rails no longer run on 3.1. Raising `required_ruby_version` to `>= 3.2` also excludes JRuby 9.4, which reports `RUBY_VERSION` 3.1.x. See #1171.
|
|
19
|
-
|
|
20
|
-
## Enhancements
|
|
21
|
-
* Added `SimpleCov.parallel_wait_timeout` (default 60 seconds), which controls how long the process that writes the final report waits for the other parallel-test workers to finish writing their resultsets before it merges. Raise it when one worker runs much heavier test files and routinely finishes well after the others, so its coverage is included in the merge and the minimum and maximum coverage checks run against the full total instead of being skipped against a partial one. See #1171.
|
|
22
|
-
|
|
23
|
-
## Bugfixes
|
|
24
|
-
* The "SimpleCov dropped N source file(s)" warning is now emitted at most once, from the process that writes the final report, instead of once per parallel worker. It was previously raised every time a result was built, so an eight-worker run produced eight copies. Fork-based runners that do not set `TEST_ENV_NUMBER`, such as Minitest's `parallelize`, match no parallel-test adapter, so SimpleCov now marks forked children (it already hooks `Process._fork`) and treats them as non-reporters when no adapter is active, leaving the process that did the forking to merge every slice and report once. See #1171.
|
|
25
|
-
* Using `[SimpleCov::Formatter::HTMLFormatter, SimpleCov::Formatter::JSONFormatter]` together no longer prints a false "coverage.json was written after this process started" warning. As of 1.0 the HTML formatter writes `coverage.json` itself, so the JSON formatter found a file its own run had just written and mistook it for a concurrent worker about to lose data. The warning is now skipped when the existing file belongs to the same merged result. Because the HTML formatter already writes `coverage.json`, listing `JSONFormatter` alongside it is redundant and can be removed. See #1171.
|
|
26
|
-
|
|
27
|
-
1.0.0.rc2 (2026-06-10)
|
|
28
|
-
======================
|
|
29
|
-
|
|
30
|
-
## Bugfixes
|
|
31
|
-
* Forked subprocesses (for example Rails' `parallelize`) are now named by a stable per-run serial rather than the child's OS process id. Because the pid changed every run, a re-run's worker results were never named the same as the previous run's and so never overwrote them. They accumulated in `.resultset.json` until `merge_timeout` dropped them, and while several runs sat inside that window together SimpleCov merged them all. When the set of files had drifted between those runs (a deleted file, a changed filter) the stale results leaked into the report, inflating the denominator and changing the coverage percentage from one run to the next. The serial sequence is identical from one run to the next, so a re-run's workers now overwrite the previous run's entries and the resultset stays bounded. See #1171.
|
|
32
|
-
* The "Excluded N result(s) older than `merge_timeout`" warning is now emitted at most once, from the reporting process, instead of once per forked worker. Every worker merges the resultset too, and the default `at_fork` sets `print_errors false` for them, but this one warning did not honor the flag, so an eight-worker run printed eight copies. See #1171.
|
|
33
|
-
* Legacy-API deprecation warnings (`track_files`, `add_filter`, `add_group`, and the rest) are now deduplicated by call site and emitted at most once per source location. A deprecated method called in a loop, or a configuration block re-evaluated once per parallel worker or spec file, previously repeated the same notice until the surrounding output was unreadable. See #1204.
|
|
34
|
-
|
|
35
|
-
1.0.0.rc1 (2026-06-02)
|
|
36
|
-
======================
|
|
37
|
-
|
|
38
|
-
## Breaking Changes
|
|
39
|
-
* JSON formatter: group stats changed from `{ "covered_percent": 80.0 }` to full stats shape `{ "covered": 8, "missed": 2, "total": 10, "percent": 80.0, "strength": 0.0 }`. The key `covered_percent` is renamed to `percent`.
|
|
40
|
-
* JSON formatter: `simplecov_json_formatter` gem is now built in. `require "simplecov_json_formatter"` continues to work via a shim.
|
|
41
|
-
* `StringFilter` now matches at path-segment boundaries. `"lib"` matches `/lib/` but no longer matches `/library/`. Use a `Regexp` filter for substring matching.
|
|
42
|
-
* `SourceFile#project_filename` now returns a truly relative path with no leading separator (e.g. `lib/foo.rb` instead of `/lib/foo.rb`). This also removes the leading `/` from file path keys in `coverage.json` and from the filename in `minimum_coverage_by_file` error messages. Anchored `RegexFilter`s that relied on a leading `/` (e.g. `%r{^/lib/}`) should be rewritten (e.g. `%r{\Alib/}`).
|
|
43
|
-
* Removed `docile` gem dependency. The `SimpleCov.configure` block is now evaluated via `instance_exec` with instance variable proxying.
|
|
44
|
-
* Removed automatic activation of `JSONFormatter` when the `CC_TEST_REPORTER_ID` environment variable is set. The default `HTMLFormatter` now emits `coverage.json` alongside the HTML report (using `JSONFormatter.build_hash` to serialize the same payload `JSONFormatter` writes), so the env-var special case is no longer needed.
|
|
45
|
-
* `SimpleCov.start` now loads the `test_frameworks` profile by default, which filters paths under `test/`, `spec/`, `features/`, and `autotest/`. Running the suite always executes 100% of the test files themselves, which inflated the overall percentage and obscured application coverage. To opt back in (e.g. to surface dead test helpers), drop the filter with `remove_filter %r{\A(test|features|spec|autotest)/}`. See #816.
|
|
46
|
-
* HTML and JSON formatters now write the "Coverage report generated for X to Y" status line (and the per-criterion totals beneath it) to stderr instead of stdout. The message is a diagnostic, not the program's output, and routing it to stdout polluted pipelines like `rspec -f json`. Suppress it entirely with `silent: true` on the formatter; redirect with `2>&1` if you want the old behavior. See #1060.
|
|
47
|
-
* Under `parallel_tests`, SimpleCov now waits in the **first** started process (via `ParallelTests.first_process?`) rather than the last. This matches the convention `parallel_tests`'s own README recommends for "do something once after all workers finish" hooks, so user code that has its own `ParallelTests.wait_for_other_processes_to_finish` in an `RSpec.after(:suite)` (or equivalent) no longer deadlocks against SimpleCov's wait when both pick the same process. As a side benefit, the previous `PARALLEL_TEST_GROUPS=1` workaround for `last_process?`'s `"" == "1"` mismatch (#1066) is no longer needed — `first_process?` handles that case naturally. **Migration:** the rare project that wired its own wait via `ParallelTests.last_process?` now hits the symmetric deadlock and must switch to `first_process?`. See #922.
|
|
48
|
-
* Removed `SimpleCov.coverage_criterion`. It was a reader/writer for a value nothing in SimpleCov ever consumed, so it duplicated `primary_coverage` without affecting any behavior. Use `primary_coverage` to choose the report's leading criterion (or the `coverage :branch, primary: true` form).
|
|
49
|
-
|
|
50
|
-
## Deprecations
|
|
51
|
-
* The configuration API has been redesigned around a smaller, more consistent set of verbs. The legacy methods continue to work but each emits a deprecation warning that names its replacement; a future release will remove them. See the "Migrating from the legacy configuration API" section in the README for the full migration table and a before/after example.
|
|
52
|
-
* `add_filter` → `skip` (identical matcher grammar; no behavior change)
|
|
53
|
-
* `add_group` → `group` (identical matcher grammar; no behavior change)
|
|
54
|
-
* `track_files` → `cover` (`cover` includes unloaded files like `track_files` did **and** restricts the report to the matching set; pass every directory you want reported, e.g. `cover "lib/**/*.rb", "app/**/*.rb"`, to keep the old additive-only behavior)
|
|
55
|
-
* `use_merging` → `merging` (same value)
|
|
56
|
-
* `enable_for_subprocesses` → `merge_subprocesses` (same value)
|
|
57
|
-
* `enable_coverage_for_eval` → `enable_coverage :eval` (folds into the same call that enables `:line` / `:branch` / `:method`)
|
|
58
|
-
* `print_error_status` (reader) → `print_errors` (the `print_error_status=` writer is unaffected for now)
|
|
59
|
-
* Calling `SimpleCov.start` from `.simplecov` is deprecated. Coverage tracking still begins for backward compatibility, but a one-time deprecation warning fires pointing the user at moving the call into `spec_helper.rb` / `test_helper.rb`; a future release will require the explicit `SimpleCov.start` from a test helper. The migration goes hand-in-hand with the bugfix below: once `SimpleCov.start` lives in the test helper, the parent process that auto-loads `.simplecov` never starts tracking and the empty-report-overwrite scenario can't arise. See #581.
|
|
60
|
-
* `# :nocov:` toggle comments (and the configurable `SimpleCov.nocov_token` / `SimpleCov.skip_token`) are deprecated in favor of the new `# simplecov:disable` / `# simplecov:enable` directives. Each file that still uses `# :nocov:` emits a one-time deprecation warning to stderr at load time pointing at the recommended replacement, and any call to `SimpleCov.nocov_token` or `SimpleCov.skip_token` (getter or setter) likewise warns. The directive will be removed in a future release.
|
|
61
|
-
* `SimpleCov::SourceFile#branches_coverage_percent` and `#methods_coverage_percent` are deprecated in favor of the uniform `covered_percent(:branch)` / `covered_percent(:method)`. `covered_percent` (and `covered_strength`) now take a criterion argument (defaulting to `:line`), so the same call reaches any criterion instead of line being the unprefixed default while branch and method had their own differently-named methods. `coverage_statistics` also now accepts a criterion (e.g. `coverage_statistics(:branch)`) to return that one `CoverageStatistics` rather than the whole Hash.
|
|
62
|
-
* `minimum_coverage_by_file` and `minimum_coverage_by_group` are deprecated in favor of the `coverage` method's `minimum_per_file` / `minimum_per_group` verbs. The legacy methods overloaded a single hash to carry both per-criterion defaults and per-path / per-group overrides, with `minimum_coverage_by_file` further distinguishing Symbol keys (criterion defaults) from String / Regexp keys (path overrides) and accepting either a bare number or a per-criterion hash as the value. The `coverage` block fixes the criterion so every threshold is a plain percentage with an `only:` target. The setter form emits a deprecation warning naming the replacement; the no-arg getter (read internally) is unchanged. Replace e.g. `minimum_coverage_by_file line: 70, 'app/x.rb' => 100` with `coverage(:line) { minimum_per_file 70; minimum_per_file 100, only: 'app/x.rb' }`. See the "Per-criterion thresholds with `coverage`" README section.
|
|
63
|
-
|
|
64
|
-
## Enhancements
|
|
65
|
-
* `simplecov uncovered` gained `--criterion line|branch|method` (default `line`) so the lowest-coverage listing can rank by branch or method coverage, not just line.
|
|
66
|
-
* Added the criterion-first `coverage` configuration method — a uniform way to configure each coverage criterion (`:line`, `:branch`, `:method`) in one place. `coverage :line do minimum 90; minimum_per_file 80; maximum_drop 5 end` (or the one-liner `coverage :branch, minimum: 80`) enables the criterion and declares its thresholds with identical syntax regardless of criterion, because the criterion is fixed by the enclosing call rather than smuggled into the argument as the historical "a bare number means line coverage, every other criterion needs a Hash" special case. Verbs: `minimum`, `maximum`, `exact`, `maximum_drop`, `minimum_per_file` (with `only:` String-path / Regexp overrides), and `minimum_per_group`. Options: `primary:` (the report's leading criterion), `oneshot:` (oneshot-lines mode for `:line`), and `:eval`. The flat `minimum_coverage` family remains as suite-wide sugar. Thresholds feed the same internal stores, so exit-code enforcement is unchanged. See the "Per-criterion thresholds with `coverage`" section in the README.
|
|
67
|
-
* JSON formatter: `coverage.json` now carries a top-level `$schema` field holding the URL of the versioned canonical JSON Schema the document conforms to, plus a human-readable `meta.schema_version` (`"major.minor"`, currently `"1.0"`). The versioned canonical lives at `schemas/coverage-v1.0.schema.json` and is immutable per version, an unversioned convenience alias at `schemas/coverage.schema.json` always tracks the latest. Downstream tools can validate inputs, generate types, or pin to a known shape, and the document-level `$schema` makes each payload self-describing. The schema version is independent of the gem version: additive changes bump minor, removals or shape changes bump major and ship as a new `schemas/coverage-vX.0.schema.json` file so prior-version consumers stay valid. `meta.commit` carries the git commit SHA the report was generated against (or null outside a git checkout), so tools can recover the exact source from history even when `source_in_json false` omits the per-file source arrays.
|
|
68
|
-
* Added `SimpleCov::ParallelAdapters` — a pluggable adapter interface for parallel test runners. SimpleCov's coordination with parallel test runners (deciding which worker does final-result work, waiting for siblings, knowing how many resultsets to expect) now routes through an adapter chain rather than hard-coding the `parallel_tests` gem's API. Two adapters ship: `ParallelTestsAdapter` wraps the historical grosser/parallel_tests gem (precise, gem-API-based); `GenericAdapter` handles any runner that follows the `TEST_ENV_NUMBER` / `PARALLEL_TEST_GROUPS` env-var convention without shipping a Ruby API. The practical impact: **parallel_rspec (and any similar env-var-only runner) now works out of the box** — previously every worker thought it was the "final" one and they clobbered each other's resultsets. Custom runners can register their own adapter via `SimpleCov::ParallelAdapters.register MyAdapter`, where `MyAdapter` subclasses `SimpleCov::ParallelAdapters::Base` and overrides the four contract methods (`active?`, `first_worker?`, `wait_for_siblings`, `expected_worker_count`). See #1065.
|
|
69
|
-
* Added `SimpleCov.ignore_branches` for opting out of synthetic `:else` branches that Ruby's `Coverage` library reports for constructs with no literal `else` keyword — exhaustive `case/in` pattern matches, `case/when` without `else`, `||=` / `&&=`, and `if` / `unless` without `else`. Variadic; only `:implicit_else` is supported today, with room for future synthetic branch types. Calling it without (or before) `enable_coverage :branch` is harmless — the setting is stored and applies once branch coverage is enabled. Explicit `else` arms still count. See #1033.
|
|
70
|
-
* Added `SimpleCov.cover` for declaring a positive coverage scope (the long-requested allowlist counterpart to `add_filter`). Accepts string globs, Regexps, blocks, or arrays of those; multiple calls union. When any `cover` matcher is configured the report drops every source file that doesn't match at least one of them, and string-glob matchers also expand on disk so files that exist but were never required during the run still appear in the report (at 0% coverage). Resolves the long-standing requests in #696 and #869. The companion `SimpleCov.no_default_skips` opts out of the filters that `SimpleCov.start` installs (hidden files, `vendor/bundle/`, test directories) so users who want to opt out wholesale don't have to call `clear_filters` themselves.
|
|
71
|
-
* `SimpleCov.formatter false` (and the equivalent `SimpleCov.formatters []`) now opts out of formatting entirely instead of raising `ConfigurationError`. `SimpleCov::Result#format!` returns `nil` when no formatter is configured. Intended for worker processes in big parallel CI runs (hundreds of jobs) where only a final `SimpleCov.collate` step needs a report — every other worker just drops its `.resultset.json` and exits without paying for HTML or multi-formatter output. See #964.
|
|
72
|
-
* Setting `TEST_ENV_NUMBER` and `PARALLEL_TEST_GROUPS` no longer triggers a spurious `"SimpleCov guessed you were running inside parallel tests but couldn't load it"` warning when the `parallel_tests` gem isn't actually installed. SimpleCov now treats a `LoadError` on the auto-require as "the user set those env vars for some other reason (custom subprocess coordination, CI sharding) and isn't using parallel_tests" and silently skips. The new `SimpleCov.parallel_tests true` / `false` setting forces the auto-require on or off when finer control is needed. See #1018.
|
|
73
|
-
* `SimpleCov.minimum_coverage_by_file` now accepts per-path overrides alongside the existing per-criterion defaults: pass String or Regexp keys to declare file- or directory-specific thresholds, e.g. `minimum_coverage_by_file line: 70, 'app/mailers/request_mailer.rb' => 100`. A String ending in `/` matches as a directory prefix; otherwise it must equal the project-relative path. Regexp keys match against the project-relative path. Per-path values may be a Numeric (primary criterion) or a per-criterion Hash; for each file the effective threshold is the defaults merged with any matching overrides (later overrides win per criterion, overrides win over defaults). The new overrides surface in `coverage.json` under the existing `errors.minimum_coverage_by_file` block. See #575.
|
|
74
|
-
* Added `SimpleCov.maximum_coverage` (and the convenience `SimpleCov.expected_coverage`, which sets `minimum_coverage` and `maximum_coverage` to the same value) so the suite can be pinned to an exact coverage figure. A drop fails per the minimum; an unexpected increase also fails, prompting you to bump the threshold up rather than silently absorbing the improvement. Accepts the same Numeric / per-criterion Hash forms as `minimum_coverage`. Exits with status 4 (`SimpleCov::ExitCodes::MAXIMUM_COVERAGE`) when violated, and surfaces in `coverage.json` under `errors.maximum_coverage`. Comparisons floor the actual percent to two decimal places, so `expected_coverage 95.42` still passes when the actual is e.g. 95.4287. See #187.
|
|
75
|
-
* Added a bundled `strict` profile (`SimpleCov.start "strict"`) that enables line, branch, and method coverage and pins the minimum threshold for each at 100%. Drops to line-only on engines without branch/method support (JRuby). See #1061.
|
|
76
|
-
* `SimpleCov.coverage_path` is now explicitly settable rather than always computed from `SimpleCov.root + SimpleCov.coverage_dir`. Setting it pins the report destination regardless of later `root` / `coverage_dir` changes — useful for out-of-tree build directories (CMake/CTest etc.) where the coverage report doesn't live under the source root. See #716.
|
|
77
|
-
* The "Coverage report generated for X to Y" status line now prints the report path relative to the current working directory when it lives under cwd, and includes the entry-point filename — `coverage/index.html` from the HTML formatter, `coverage/coverage.json` from the JSON formatter — so the line points at a concrete file (and is clickable in terminals that hyperlink paths). Paths outside cwd stay absolute. See #197.
|
|
78
|
-
* Added `SimpleCov.disable_coverage(criterion)` so a project can opt out of line coverage entirely — e.g. `enable_coverage :branch; disable_coverage :line` for a branch-only run. `SimpleCov.start` now raises `SimpleCov::ConfigurationError` when every criterion has been disabled. The formatter summary and JSON output emit only the criteria that were actually measured, so a branch-only run produces no `Line coverage:` line, no `lines` key in `coverage.json`, and no zero-padded line numbers in the HTML report. See #845.
|
|
79
|
-
* Added `SimpleCov.remove_filter(arg)` to drop a specific filter (matching by `filter_argument`) and `SimpleCov.clear_filters` to wipe the entire chain. Useful for selectively turning off one of the defaults loaded by `SimpleCov.start` — e.g. `remove_filter(/\A\..*/)` to stop hiding paths that begin with a dot. The README's "Default filters" section enumerates what's loaded by default and how to disable each piece. See #803.
|
|
80
|
-
* Terminal output is now colorized when stderr is a TTY: coverage percentages in the formatter summary line and threshold-violation messages are rendered green (>= 90%), yellow (>= 75%), or red (< 75%) — matching the HTML report's thresholds. The "SimpleCov failed with exit N…" line is red and the "Stopped processing SimpleCov…" line is yellow. Respects `NO_COLOR` (force off, per no-color.org) and `FORCE_COLOR` (force on); `NO_COLOR` wins if both are set. See #1157.
|
|
81
|
-
* CLI subcommands `coverage`, `report`, `uncovered`, and `diff` now colorize their printed percentages by the same threshold (and `diff` colors regressions red, improvements green). Auto-detect based on whether stdout is a TTY; the same `NO_COLOR` / `FORCE_COLOR` env vars apply. Each subcommand also accepts a `--no-color` flag as a per-invocation override.
|
|
82
|
-
* Added `# simplecov:disable` / `# simplecov:enable` directive comments for selectively skipping `line`, `branch`, and `method` coverage. Block form (own line) opens a region until the matching `# simplecov:enable`; inline form (trailing a code line) skips just that line. Categories may be combined (`# simplecov:disable line, branch`); omitting categories targets all three. Any trailing text is treated as a free-form reason and discarded (e.g. `# simplecov:disable line legacy adapter`). Directive markers inside string literals or heredocs are ignored.
|
|
83
|
-
* Added `SimpleCov.source_in_json` (default true) to make the per-file `source` array in `coverage.json` opt-out. Tools that read the project's source files from disk don't need the embedded copy, and on larger projects it dominates the JSON payload. The HTML report's `coverage_data.js` still embeds source unconditionally because the client-side viewer renders source from there. See #1143.
|
|
84
|
-
* JSON formatter: `meta.timestamp` is now emitted with millisecond precision (`iso8601(3)`) so the concurrent-overwrite warning can distinguish writes within the same wall-clock second
|
|
85
|
-
* JSON formatter: added `total` section with aggregate coverage statistics (covered, missed, total, percent, strength) for line, branch, and method coverage. Line stats additionally include `omitted` (count of blank/comment lines, i.e. lines that cannot be covered)
|
|
86
|
-
* JSON formatter: per-file output now includes `total_lines`, `lines_covered_percent`, and when enabled: `branches_covered_percent`, `methods` array, and `methods_covered_percent`
|
|
87
|
-
* JSON formatter: group stats now include full statistics for all enabled coverage types, not just line coverage percent
|
|
88
|
-
* JSON formatter: added `silent:` keyword to `JSONFormatter.new` to suppress console output
|
|
89
|
-
* Merged `simplecov-html` formatter into the main gem. A backward-compatibility shim ensures `require "simplecov-html"` still works.
|
|
90
|
-
* Merged `simplecov_json_formatter` into the main gem. A backward-compatibility shim ensures `require "simplecov_json_formatter"` still works.
|
|
91
|
-
* `CommandGuesser` now appends the framework name to parallel test data (e.g. `"RSpec (1/2)"` instead of `"(1/2)"`)
|
|
92
|
-
* `SimpleCov::Result.new` is roughly 7× faster for already-string-keyed input (the `SimpleCov.collate` hot path). The previous implementation deep-cloned each file's coverage data with `JSON.parse(JSON.dump(coverage))` per source file — a useful normalization for live `Coverage.result` symbol keys, but pure overhead for resultsets loaded from disk that already have string keys. `Result` now stringifies the outer hash keys with `transform_keys` only when needed; the inner branch/method-key shape is already handled by `SourceFile#restore_ruby_data_structure`. See #916.
|
|
93
|
-
|
|
94
|
-
## Bugfixes
|
|
95
|
-
* Added `:eval_generated` tokens to `SimpleCov.ignore_branches` and the new `SimpleCov.ignore_methods` so projects using macros like Rails' `delegate` (or any pattern that calls `module_eval(body, __FILE__, __LINE__)`) can drop the synthetic branch and method entries those macros inject. Ruby's `Coverage` attributes eval'd code to the caller's `__FILE__` / `__LINE__`, so a `delegate :foo, to: :bar` line surfaces as if it had a `def foo` and an `if` branch right there. Detection uses Prism to walk the static source and treats any Coverage entry whose start_line lacks a real `def` keyword (for methods) or branch construct (for branches) as eval-generated. Opt in with `ignore_methods :eval_generated` and / or `ignore_branches :eval_generated`. Prism ships with Ruby 3.3+; on older Rubies `gem install prism` enables the filter, otherwise the setting is a no-op. See #1046.
|
|
96
|
-
* Files added via `cover` / `track_files` that were never `require`'d during the run now contribute branch and method entries to the report, not just lines. Previously `SimulateCoverage` left those fields as empty hashes (because parsing source ourselves felt risky), which made unloaded files invisible to the branch and method denominators while their lines DID count — so a `cover "{app,lib}/**/*.rb"` glob over files without specs silently inflated branch% relative to line% (the OP's reproduction was via SonarQube, which surfaces the asymmetry more visibly than the SimpleCov HTML report). Branches and methods are now enumerated statically via `SimpleCov::StaticCoverageExtractor`, which uses Prism to walk the AST and emits Coverage-shaped tuples without loading the file. The shape matches what Ruby's own `Coverage` library reports for the same source: `:if` / `:case` / `:while` / `:until` constructs plus their `:then` / `:else` / `:when` / `:in` / `:body` arms, with the synthetic `:else` for case-without-explicit-else that the `ignore_branches :implicit_else` setting (see Enhancements) targets. Prism is bundled with Ruby 3.3+; on older Rubies `gem install prism` enables the fix, otherwise SimulateCoverage falls back to the previous "empty hashes" behavior. See #1059.
|
|
97
|
-
* HTML report: two groups whose names share an alphanumeric suffix but differ only in a leading non-letter (e.g. `">100LOC"` / `"<10LOC"`, or any pair using different special characters) no longer render into the same DOM container. The JS that built HTML ids from group names stripped every non-letter prefix and then every remaining non-alphanumeric char, so both names sanitized to `"LOC"` and the second group silently replaced the first in the rendered tabs. The new encoding (`"g-" + each-non-id-char-as-hex`) preserves uniqueness across all input shapes. See #1038.
|
|
98
|
-
* HTML report: filenames containing `"` or `'` characters are now escaped when rendered into `title="..."` attributes. The previous DOM-based `escapeHTML` only escaped `&`, `<`, and `>`, so a project with such filenames could break out of the attribute. The replacement encodes all five HTML-attribute-sensitive characters via a `replace` callback (also avoids allocating a DOM node per call).
|
|
99
|
-
* HTML report: files with literally 0% branch or method coverage now display 0% instead of 100%. The per-file row rendering used `f.branches_covered_percent || 100.0` (and the method equivalent), which treated a real `0` as falsy and substituted the disabled-criterion fallback. The check now distinguishes "criterion disabled" (`undefined`) from "criterion measured zero" (`0`).
|
|
100
|
-
* `SimpleCov::Result` now warns when it drops source files because their absolute paths aren't on the local filesystem, instead of silently producing an empty `0 / 0 (100.00%)` report. The most common trigger is `SimpleCov.collate` invoked from a machine or working directory different from where the individual resultsets were generated — when *every* entry is missing the warning explicitly names that case and points at the issue; when only some are missing the warning is quieter and lists up to five paths with a `(+N more)` suffix. See #980.
|
|
101
|
-
* Files added via `track_files` that were never loaded now use the same line classification as loaded files. Previously, `SimulateCoverage` ran the file through `LinesClassifier`, which marks every non-blank, non-comment line as relevant — so a multi-line method chain `@x = a.foo.bar` reported 4 relevant lines for the unloaded copy and 2 for the loaded copy, throwing off per-file and overall percentages. `SimulateCoverage` now uses `Coverage.line_stub` (the same stub Ruby would have produced if the file were required), then overlays `# :nocov:` toggles and `# simplecov:disable line` directive ranges that the runtime doesn't know about. The two paths now agree on every shape: multi-line statements, `end` keywords, blank lines, and SimpleCov-specific exclusion comments. Some projects will see their `tracked_files` percentages shift as a result. See #654.
|
|
102
|
-
* Fix the parent-process / subprocess race where a Rakefile (or Rails `Bundler.require`) caused `.simplecov` to auto-load `SimpleCov.start` in the rake parent, which then shelled out to a test runner subprocess; the subprocess wrote a correct report, then the parent's `at_exit` would clobber it with an empty 0% report. Three layers of defense now apply: (1) `.simplecov` is treated as configuration only and no longer starts tracking from the parent (see Deprecations); (2) `ResultMerger.store_result` merges incoming entries with same-`command_name` entries that were written after our `process_start_time` instead of overwriting them; (3) `SimpleCov.at_exit_behavior` defers entirely when our merged result is empty and `coverage/.last_run.json` is fresher than this process. See #581.
|
|
103
|
-
* Don't report misleading 100% branch/method coverage for files added via `track_files` that were never loaded. See #902
|
|
104
|
-
* Fix HTML formatter tab bar layout: dark mode toggle no longer wraps onto two lines, and tabs connect seamlessly with the content panel
|
|
105
|
-
* Allow `SimpleCov.root('/')` so files outside the conventional project root can be tracked (e.g. Docker layouts where code and tests are siblings at `/`). The root-prefix regex no longer doubles the separator (`//`), and `project_name` no longer crashes when `root` has no parent segment. The user-facing `:root_filter` profile and the unconditional `UselessResultsRemover` now share a single regex source instead of computing it independently. See #860.
|
|
106
|
-
* When `SimpleCov.start` runs after `require "minitest/autorun"` (e.g. under `Rake::TestTask` or `Minitest::TestTask`, which shell out as `ruby -e 'require "minitest/autorun"; ...'`), automatically set `external_at_exit` and route the report through `Minitest.after_run`. Previously, the `at_exit` LIFO order meant SimpleCov formatted a 0% report before Minitest ran. The opposite ordering (SimpleCov first) is still handled by `lib/minitest/simplecov_plugin.rb`. See #1032, #1099, and #1112.
|
|
107
|
-
|
|
108
|
-
0.22.1 (2024-09-02)
|
|
109
|
-
==========
|
|
110
|
-
|
|
111
|
-
## Enhancements
|
|
112
|
-
|
|
113
|
-
* You can now define `minimum_coverage_by_group` - See https://github.com/simplecov-ruby/simplecov/pull/1105. Thanks [@mikhliuk-k](https://github.com/mikhliuk-k)!
|
|
114
|
-
* `minimum_coverage_by_file` prints the name of the violating file. - [@philipritchey](https://github.com/philipritchey)
|
|
115
|
-
|
|
116
|
-
0.22.0 (2022-12-23)
|
|
117
|
-
==========
|
|
118
|
-
|
|
119
|
-
## Enhancements
|
|
120
|
-
* On Ruby 3.2+, you can now use the new Coverage library feature for `eval` - See https://github.com/simplecov-ruby/simplecov/pull/1037. Thanks [@mame](https://github.com/mame)!
|
|
121
|
-
|
|
122
|
-
## Bugfixes
|
|
123
|
-
* Fix for making the test suite pass against the upcoming Ruby 3.2 - See https://github.com/simplecov-ruby/simplecov/pull/1035. Thanks [@mame](https://github.com/mame)
|
|
124
|
-
|
|
125
|
-
0.21.2 (2021-01-09)
|
|
126
|
-
==========
|
|
127
|
-
|
|
128
|
-
## Bugfixes
|
|
129
|
-
* `maximum_coverage_drop` won't fail any more if `.last_run.json` is still in the old format. Thanks [@petertellgren](https://github.com/petertellgren)
|
|
130
|
-
* `maximum_coverage_drop` won't fail if an expectation is specified for a previous unrecorded criterion, it will just pass (there's nothing, so nothing to drop)
|
|
131
|
-
* fixed bug in `maximum_coverage_drop` calculation that could falsely report it had dropped for minimal differences
|
|
132
|
-
|
|
133
|
-
0.21.1 (2021-01-04)
|
|
134
|
-
==========
|
|
135
|
-
|
|
136
|
-
## Bugfixes
|
|
137
|
-
* `minimum_coverage_by_file` works again as expected (errored out before 😱)
|
|
138
|
-
|
|
139
|
-
0.21.0 (2021-01-03)
|
|
140
|
-
==========
|
|
141
|
-
|
|
142
|
-
The "Collate++" release making it more viable for big CI setups by limiting memory consumption. Also includes some nice new additions for branch coverage settings.
|
|
143
|
-
|
|
144
|
-
## Enhancements
|
|
145
|
-
* Performance of `SimpleCov.collate` improved - it should both run faster and consume much less memory esp. when run with many files (memory consumption should not increase with number of files any more)
|
|
146
|
-
* Can now define the minimum_coverage_by_file, maximum_coverage_drop and refuse_coverage_drop by branch as well as line coverage. Thanks to [@jemmaissroff](https://github.com/jemmaissroff)
|
|
147
|
-
* Can set primary coverage to something other than line by setting `primary_coverage :branch` in SimpleCov Configuration. Thanks to [@jemmaissroff](https://github.com/jemmaissroff)
|
|
148
|
-
|
|
149
|
-
## Misc
|
|
150
|
-
* reduce gem size by splitting Changelog into `Changelog.md` and a pre 0.18 `Changelog.old.md`, the latter of which is not included in the gem
|
|
151
|
-
* The interface of `ResultMeger.merge_and_store` is changed to support the `collate` performance improvements mentioned above. It's not considered an official API, hence this is not in the breaking section. For people using it to merge results from different machines, it's recommended to migrate to [collate](https://github.com/simplecov-ruby/simplecov#merging-test-runs-under-different-execution-environments).
|
|
152
|
-
|
|
153
|
-
0.20.0 (2020-11-29)
|
|
154
|
-
==========
|
|
155
|
-
|
|
156
|
-
The "JSON formatter" release. Starting now a JSON formatter is included by default in the release. This is mostly done for Code Climate reasons, you can find more details [in this issue](https://github.com/codeclimate/test-reporter/issues/413).
|
|
157
|
-
Shipping with so much by default is sub-optimal, we know. It's the long term plan to also provide `simplecov-core` without the HTML or JSON formatters for those who don't need them/for other formatters to rely on.
|
|
158
|
-
|
|
159
|
-
## Enhancements
|
|
160
|
-
* `simplecov_json_formatter` included by default ([docs](https://github.com/simplecov-ruby/simplecov#json-formatter)), this should enable the Code Climate test reporter to work again once it's updated
|
|
161
|
-
* invalidate internal cache after switching `SimpleCov.root`, should help with some bugs
|
|
162
|
-
|
|
163
|
-
0.19.1 (2020-10-25)
|
|
164
|
-
==========
|
|
165
|
-
|
|
166
|
-
## Bugfixes
|
|
167
|
-
|
|
168
|
-
* No more warnings triggered by `enable_for_subprocesses`. Thanks to [@mame](https://github.com/mame)
|
|
169
|
-
* Avoid trying to patch `Process.fork` when it isn't available. Thanks to [@MSP-Greg](https://github.com/MSP-Greg)
|
|
170
|
-
|
|
171
|
-
0.19.0 (2020-08-16)
|
|
172
|
-
==========
|
|
173
|
-
|
|
174
|
-
## Breaking Changes
|
|
175
|
-
* Dropped support for Ruby 2.4, it reached EOL
|
|
176
|
-
|
|
177
|
-
## Enhancements
|
|
178
|
-
* observe forked processes (enable with SimpleCov.enable_for_subprocesses). See [#881](https://github.com/simplecov-ruby/simplecov/pull/881), thanks to [@robotdana](https://github.com/robotdana)
|
|
179
|
-
* SimpleCov distinguishes better that it stopped processing because of a previous error vs. SimpleCov is the originator of said error due to coverage requirements.
|
|
180
|
-
|
|
181
|
-
## Bugfixes
|
|
182
|
-
* Changing the `SimpleCov.root` combined with the root filtering didn't work. Now they do! Thanks to [@deivid-rodriguez](https://github.com/deivid-rodriguez) and see [#894](https://github.com/simplecov-ruby/simplecov/pull/894)
|
|
183
|
-
* in parallel test execution it could happen that the last coverage result was written to disk when it didn't complete yet, changed to only write it once it's the final result
|
|
184
|
-
* if you run parallel tests only the final process will report violations of the configured test coverage, not all previous processes
|
|
185
|
-
* changed the parallel_tests merging mechanisms to do the waiting always in the last process, should reduce race conditions
|
|
186
|
-
|
|
187
|
-
## Noteworthy
|
|
188
|
-
* The repo has moved to https://github.com/simplecov-ruby/simplecov - everything stays the same, redirects should work but you might wanna update anyhow
|
|
189
|
-
* The primary development branch is now `main`, not `master` anymore. If you get simplecov directly from github change your reference. For a while `master` will still be occasionally updated but that's no long term solion.
|
|
190
|
-
|
|
191
|
-
0.18.5 (2020-02-25)
|
|
192
|
-
===================
|
|
193
|
-
|
|
194
|
-
Can you guess? Another bugfix release!
|
|
195
|
-
|
|
196
|
-
## Bugfixes
|
|
197
|
-
* minitest won't crash if SimpleCov isn't loaded - aka don't execute SimpleCov code in the minitest plugin if SimpleCov isn't loaded. Thanks to [@edariedl](https://github.com/edariedl) for the report of the peculiar problem in [#877](https://github.com/simplecov-ruby/simplecov/issues/877).
|
|
198
|
-
|
|
199
|
-
0.18.4 (2020-02-24)
|
|
200
|
-
===================
|
|
201
|
-
|
|
202
|
-
Another small bugfix release 🙈 Fixes SimpleCov running with rspec-rails, which was broken due to our fixed minitest integration.
|
|
203
|
-
|
|
204
|
-
## Bugfixes
|
|
205
|
-
* SimpleCov will run again correctly when used with rspec-rails. The excellent bug report [#873](https://github.com/simplecov-ruby/simplecov/issues/873) by [@odlp](https://github.com/odlp) perfectly details what went wrong. Thanks to [@adam12](https://github.com/adam12) for the fix [#874](https://github.com/simplecov-ruby/simplecov/pull/874).
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
0.18.3 (2020-02-23)
|
|
209
|
-
===========
|
|
210
|
-
|
|
211
|
-
Small bugfix release. It's especially recommended to upgrade simplecov-html as well because of bugs in the 0.12.0 release.
|
|
212
|
-
|
|
213
|
-
## Bugfixes
|
|
214
|
-
* Fix a regression related to file encodings as special characters were missing. Furthermore we now respect the magic `# encoding: ...` comment and read files in the right encoding. Thanks ([@Tietew](https://github.com/Tietew)) - see [#866](https://github.com/simplecov-ruby/simplecov/pull/866)
|
|
215
|
-
* Use `Minitest.after_run` hook to trigger post-run hooks if `Minitest` is present. See [#756](https://github.com/simplecov-ruby/simplecov/pull/756) and [#855](https://github.com/simplecov-ruby/simplecov/pull/855) thanks ([@adam12](https://github.com/adam12))
|
|
216
|
-
|
|
217
|
-
0.18.2 (2020-02-12)
|
|
218
|
-
===================
|
|
219
|
-
|
|
220
|
-
Small release just to allow you to use the new simplecov-html.
|
|
221
|
-
|
|
222
|
-
## Enhancements
|
|
223
|
-
* Relax simplecov-html requirement so that you're able to use [0.12.0](https://github.com/simplecov-ruby/simplecov-html/blob/main/CHANGELOG.md#0120-2020-02-12)
|
|
224
|
-
|
|
225
|
-
0.18.1 (2020-01-31)
|
|
226
|
-
===================
|
|
227
|
-
|
|
228
|
-
Small Bugfix release.
|
|
229
|
-
|
|
230
|
-
## Bugfixes
|
|
231
|
-
* Just putting `# :nocov:` on top of a file or having an uneven number of them in general works again and acts as if ignoring until the end of the file. See [#846](https://github.com/simplecov-ruby/simplecov/issues/846) and thanks [@DannyBen](https://github.com/DannyBen) for the report.
|
|
232
|
-
|
|
233
|
-
0.18.0 (2020-01-28)
|
|
234
|
-
===================
|
|
235
|
-
|
|
236
|
-
Huge release! Highlights are support for branch coverage (Ruby 2.5+) and dropping support for EOL'ed Ruby versions (< 2.4).
|
|
237
|
-
Please also read the other beta patch notes.
|
|
238
|
-
|
|
239
|
-
You can run with branch coverage by putting `enable_coverage :branch` into your SimpleCov configuration (like the `SimpleCov.start do .. end` block)
|
|
240
|
-
|
|
241
|
-
## Enhancements
|
|
242
|
-
* You can now define the minimum expected coverage by criterion like `minimum_coverage line: 90, branch: 80`
|
|
243
|
-
* Memoized some internal data structures that didn't change to reduce SimpleCov overhead
|
|
244
|
-
* Both `FileList` and `SourceFile` now have a `coverage` method that returns a hash that points from a coverage criterion to a `CoverageStatistics` object for uniform access to overall coverage statistics for both line and branch coverage
|
|
245
|
-
|
|
246
|
-
## Bugfixes
|
|
247
|
-
* we were losing precision by rounding the covered strength early, that has been removed. **For Formatters** this also means that you may need to round it yourself now.
|
|
248
|
-
* Removed an inconsistency in how we treat skipped vs. irrelevant lines (see [#565](https://github.com/simplecov-ruby/simplecov/issues/565)) - SimpleCov's definition of 100% is now "You covered everything that you could" so if coverage is 0/0 that's counted as a 100% no matter if the lines were irrelevant or ignored/skipped
|
|
249
|
-
|
|
250
|
-
## Noteworthy
|
|
251
|
-
* `FileList` stopped inheriting from Array, it includes Enumerable so if you didn't use Array specific methods on it in formatters you should be fine
|
|
252
|
-
* We needed to change an internal file format, which we use for merging across processes, to accommodate branch coverage. Sadly CodeClimate chose to use this file to report test coverage. Until a resolution is found the code climate test reporter won't work with SimpleCov for 0.18+, see [this issue on the test reporter](https://github.com/codeclimate/test-reporter/issues/413).
|
|
253
|
-
|
|
254
|
-
0.18.0.beta3 (2020-01-20)
|
|
255
|
-
========================
|
|
256
|
-
|
|
257
|
-
## Enhancements
|
|
258
|
-
* Instead of ignoring old `.resultset.json`s that are inside the merge timeout, adapt and respect them
|
|
259
|
-
|
|
260
|
-
## Bugfixes
|
|
261
|
-
* Remove the constant warning printing if you still have a `.resultset.json` in pre 0.18 layout that is within your merge timeout
|
|
262
|
-
|
|
263
|
-
0.18.0.beta2 (2020-01-19)
|
|
264
|
-
===================
|
|
265
|
-
|
|
266
|
-
## Enhancements
|
|
267
|
-
* only turn on the requested coverage criteria (when activating branch coverage before SimpleCov would also instruct Ruby to take Method coverage)
|
|
268
|
-
* Change how branch coverage is displayed, now it's `branch_type: hit_count` which should be more self explanatory. See [#830](https://github.com/simplecov-ruby/simplecov/pull/830) for an example and feel free to give feedback!
|
|
269
|
-
* Allow early running exit tasks and avoid the `at_exit` hook through the `SimpleCov.run_exit_tasks!` method. (thanks [@macumber](https://github.com/macumber))
|
|
270
|
-
* Allow manual collation of result sets through the `SimpleCov.collate` entrypoint. See the README for more details (thanks [@ticky](https://github.com/ticky))
|
|
271
|
-
* Within `case`, even if there is no `else` branch declared show missing coverage for it (aka no branch of it). See [#825](https://github.com/simplecov-ruby/simplecov/pull/825)
|
|
272
|
-
* Stop symbolizing all keys when loading cache (should lead to be faster and consume less memory)
|
|
273
|
-
* Cache whether we can use/are using branch coverage (should be slightly faster)
|
|
274
|
-
|
|
275
|
-
## Bugfixes
|
|
276
|
-
* Fix a crash that happened when an old version of our internal cache file `.resultset.json` was still present
|
|
277
|
-
|
|
278
|
-
0.18.0.beta1 (2020-01-05)
|
|
279
|
-
===================
|
|
280
|
-
|
|
281
|
-
This is a huge release highlighted by changing our support for ruby versions to 2.4+ (so things that aren't EOL'ed) and finally adding branch coverage support!
|
|
282
|
-
|
|
283
|
-
This release is still beta because we'd love for you to test out branch coverage and get your feedback before doing a full release.
|
|
284
|
-
|
|
285
|
-
On a personal note from [@PragTob](https://github.com/PragTob/) thanks to [ruby together](https://rubytogether.org/) for sponsoring this work on SimpleCov making it possible to deliver this and subsequent releases.
|
|
286
|
-
|
|
287
|
-
## Breaking
|
|
288
|
-
* Dropped support for all EOL'ed rubies meaning we only support 2.4+. Simplecov can no longer be installed on older rubies, but older simplecov releases should still work. (thanks [@deivid-rodriguez](https://github.com/deivid-rodriguez))
|
|
289
|
-
* Dropped the `rake simplecov` task that "magically" integreated with rails. It was always undocumented, caused some issues and [had some issues](https://github.com/simplecov-ruby/simplecov/issues/689#issuecomment-561572327). Use the integration as described in the README please :)
|
|
290
|
-
|
|
291
|
-
## Enhancements
|
|
292
|
-
|
|
293
|
-
* Branch coverage is here! Please try it out and test it! You can activate it with `enable_coverage :branch`. See the README for more details. This is thanks to a bunch of people most notably [@som4ik](https://github.com/som4ik), [@tycooon](https://github.com/tycooon), [@stepozer](https://github.com/stepozer), [@klyonrad](https://github.com/klyonrad) and your humble maintainers also contributed ;)
|
|
294
|
-
* If the minimum coverage is set to be greater than 100, a warning will be shown. See [#737](https://github.com/simplecov-ruby/simplecov/pull/737) (thanks [@belfazt](https://github.com/belfazt))
|
|
295
|
-
* Add a configuration option to disable the printing of non-successful exit statuses. See [#747](https://github.com/simplecov-ruby/simplecov/pull/746) (thanks [@JacobEvelyn](https://github.com/JacobEvelyn))
|
|
296
|
-
* Calculating 100% coverage is now stricter, so 100% means 100%. See [#680](https://github.com/simplecov-ruby/simplecov/pull/680) thanks [@gleseur](https://github.com/gleseur)
|
|
297
|
-
|
|
298
|
-
## Bugfixes
|
|
299
|
-
|
|
300
|
-
* Add new instance of `Minitest` constant. The `MiniTest` constant (with the capital T) will be removed in the next major release of Minitest. See [#757](https://github.com/simplecov-ruby/simplecov/pull/757) (thanks [@adam12](https://github.com/adam12))
|
|
301
|
-
|
|
302
|
-
Older Changelogs
|
|
303
|
-
================
|
|
304
|
-
|
|
305
|
-
Looking for older changelogs? Please check the [old Changelog](https://github.com/simplecov-ruby/simplecov/blob/main/CHANGELOG.old.md)
|