Repository navigation
Commit 1fd3af5
Open-source readiness: review fixes, README, licensing and docs (#12)
* Fix two shipped examples that told people to type the wrong keyword
WolframAlpha's example read `wa 42 miles in km`, but its only keyword is
`wolfram` and `wa` belongs to WhatsApp. The browse list prints the
example verbatim under each row, so the page was telling people to type a
keyword that opens somebody else's site. WhatsApp had the mirror of the
same slip, showing `whatsapp` when its keyword is `wa`.
A test now collects every example whose first word is not one of that
command's own keywords, so the next one fails the build. It is one test
rather than one per command: a failure should name every row that
drifted, not just the first.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Rewrite the README as the front door of a public repository
It opened with install instructions and buried what the thing is. A
stranger now gets two sentences and an example first, then the
not-affiliated-with-Meta line, then install, then the one design
decision that explains the rest: the first word of a query is always a
command when it matches a keyword, and the escape hatch that makes that
liveable.
Corrections found while checking the text against the code: the GitHub
username setting is read only by `gh me`, not by `pr` and `iss`; the
fallback engine has five presets, not two; the shipped table was missing
Goodreads and the meta keywords; the first run has a Skip button the
text did not mention. Adds CI and licence badges, the pinned Node and
pnpm versions, and a marked placeholder for the three screenshots the
repository still needs.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Null-prototype every lookup table an argument can index
A security pass found `gh facebook/react constructor` building
`https://github.com/facebook/react/function Object() { [native code] }`.
`GITHUB_TABS` was a plain object literal, so a lowercase Object.prototype
key answered truthy and was interpolated into the path.
Nothing escaped the origin and nothing was exploitable: the value always
lands after the encoded repo path and carries no ? or #, so the worst
case was a 404 from a query nobody types. But this is exactly the shape
AGENTS.md invariant 17 exists for, in a module the invariant does not
name, so all five tables that an argument or a user-edited URL can index
are null-prototype now: the two GitHub ones, the AI aliases, the Drive
app types and the meta route parameters.
`normalizeTemplates` in storage.ts joins them. It was the one override
map the parser built on a plain object, and a string assigned to
`__proto__` there is swallowed by the inherited setter rather than
stored, so a key could go missing without the parser saying so.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Make the privacy policy exhaustive about where data is kept
It enumerated two stores and the extension uses three. The options page
also writes `bunnylol.collapsed` to its own `localStorage`, holding the
list of folded shortcut groups. The substance of the policy was never in
doubt, since that value is per-machine view state that never leaves the
machine, but a document whose whole worth is that it is complete cannot
omit a store a reader will find by grepping for the API.
Also corrects the tab attribution. Opening a tab was credited to the
popup alone; the omnibox and the install-time welcome tab do it too. All
three use only create and update, so the load-bearing claim, that the
`tabs` permission is not requested and no page can be read, is unchanged.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Drop the internal handover doc and keep the facts worth keeping
docs/handoff.md was written for the next agent working on the release,
not for anybody who will read this repository. It cited eleven paths
under a gitignored directory that no clone will have, described a branch
and a pull request as in flight, listed manual browser checks as still
owed, and said of itself that it was probably deleted before the merge.
It was not. Publishing it advertises unfinished QA and explains nothing
a contributor needs.
The one durable section was its list of non-obvious facts that bit
somebody during development. The seven that were not already recorded
move into the AGENTS.md rules, which is where a future reader will look:
the relative meta URLs, the preview substituting at the registry index,
re-minted ids having to be rewritten in disabled and deleted, the vitest
css flag that stops the token assertions passing vacuously, the flat-hex
accent the icon generator parses, the harness class that must not reach
the shipped sheet, and what hasOnboarded means on a profile that never
answered the picker.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Correct the changelog where it contradicted itself and the code
The 1.1.0 entry described the status pill twice and incompatibly: once
under Changed as saying "Shortcuts active", once under Removed as having
lost that state. The build produces neither string on a healthy profile,
because the pill is silent. The two entries are now one that says what
the release actually did.
The Goodreads line claimed the same release both dropped and restored
it, which is true of the development history and useless to a reader.
Every link at the foot of the file pointed at a tag that does not exist,
so all three 404 on the page a stranger scrolls to. The 1.0.0 link is
gone with a note that the version was never published, and the 1.1.0
link now points at a release tag rather than a comparison.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Disclaim the Meta affiliation on the screen that claims it
AGENTS.md requires the README and any listing copy to say the project is
not affiliated with Meta. Both did. The extension itself did not, and
the welcome screen opened with "A rebuild of an internal tool at Meta",
which is the strongest affiliation claim anywhere in the project and the
only one a user or a store reviewer meets at runtime.
The sentence now says an independent rebuild of the command bar used
inside Meta, and a quieter line under it disclaims affiliation,
endorsement and sponsorship outright. The rule in AGENTS.md is widened
to cover the extension's own UI, since that is the place it was just
broken.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Finish the repository for a first-time visitor
Six things a stranger or a store reviewer would hit.
The bug report form required the rule-status text and gave an example
string this build cannot produce. On the commonest bug, a healthy
profile sending a shortcut to the wrong place, there is no pill at all,
so the field could not be answered honestly. It is optional now and says
that nothing shown is a fine answer.
The shipped zip carried the font licence but not this project's own.
LICENSE moves into public/ so the packer picks it up, which is what MIT
asks for when the software is redistributed.
store/listing.md holds the Web Store copy. The two paragraphs that are
compliance text rather than marketing, the search-behaviour disclosure
and the non-affiliation line, are quoted from the submission crib
verbatim so neither can be softened while somebody is pasting fields
into a dashboard under time pressure.
The crib itself named the rule-status pill in its suggested screenshot
set, which is now a shot of nothing, and told the reader to find a
published URL for the privacy policy when the dashboard accepts the
file's own GitHub URL.
CONTRIBUTING gains what a contributor cannot infer: one maintainer, a
week for a reply, what a major and a minor mean here given that the
stored state format is the compatibility surface, and the release steps
including building the zip fresh rather than trusting one left in
release/.
Dependabot watches the GitHub Actions pins only. Those are third-party
code running against this repository and nobody notices when one goes
stale. npm is left out on purpose: four devDependencies that move rarely
are the policy, not an oversight.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Fix three ways the Shortcuts page lost the user's place or its state
A review of the Hidden shortcuts work found these, none of which any
test could see: the repo has no DOM environment, so every view in it is
untested by construction.
Start over left the Hidden shortcuts group unfolded. The collapse store
records ids whose fold differs from the default, and `expandAll` adds
every default-folded id on purpose, because the Expand all button has to
be able to open that group. `forgetCollapsed` is not that button, it is
the reset that puts a profile back to how it was installed, so a user
who declined two packs landed on the page of dead rows the folded
default exists to prevent. `CollapseState` gains `reset`.
Flipping any switch dropped keyboard focus to the body. `move` restored
focus before `applyFilter` had decided visibility, so on the default
path, with the hidden group folded, the row was inside a
`display: none` subtree where focus is a silent no-op. `move` now
returns the element and the caller focuses it after `applyFilter`, which
is the order `turnOn` already used. Deleting a row had the same hole
with nothing to catch it; focus goes to the filter box.
The "omnibox only" badge went stale. It was computed once per render for
rows that rendered enabled, so switching a row on never added one and a
row kept its badge under Hidden shortcuts. `applyFilter` writes it now,
alongside the counts it already owns, off a memoized keyword set.
Also corrects two comments that claimed `turnOn` empties the list it
walks. It does not: `move` reassigns the array rather than mutating it.
A confidently wrong comment is what makes a reviewer skip the bug under
it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Route the exempt-keyword field through the one validation boundary
AGENTS.md invariant 6 says every alias check goes through validate.ts
and that a new surface adds a call site rather than a local rule. The
Exempt keywords field re-derived one of the three rules by hand, testing
only for whitespace. So `\gh` and `=npm` were accepted and stored, where
they can never match anything, because resolve strips that prefix before
the key map is consulted. The user got a permanent chip that did
nothing, and an arbitrarily long paste was stored too.
Also from the same review:
`commitSettings` swallowed its failures while its two siblings reject,
and it did not roll back the state it had already applied optimistically,
so a failed write left the page and every render after it showing a
value that was not in storage. It now rejects like the others and
restores the previous settings slice, not a whole snapshot, so a write
that landed while this one was in flight is not undone by its failure.
Dead code from the cards and the pill that went away: the `ok` status
tone, which nothing can produce now that a healthy sync is silent, and
`editedFields`, whose only consumer was its own test. `countShortcuts`
moves from a view into lib/text.ts beside `countShipped`, where the
helpers every surface shares live.
`dispatchToast` keeps its name, since renaming the stored field would
read as off for every profile written so far, and gains a comment saying
so.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Split storage.ts into the two families it always had
917 lines and 42 functions with no dividers, holding two complete
parallel families plus the chrome I/O. They differ in the one way that
matters, which is what they do with bad input, and nothing in the file
said which one a reader was in.
`storage/normalize.ts` is the lenient reader: any blob in, a usable
state out, and it never throws. `storage/parse-import.ts` is the strict
parser: it refuses a bad file with a message naming what is wrong.
`storage/shared.ts` holds what both need. `storage.ts` keeps the I/O,
the export and the public surface, so every importer is unchanged and
the test file needed no edit at all, not even an import path.
Each module docstring now opens with its own bad-input behaviour, since
invariant 17 turns on the difference between them.
Function bodies and their comments travelled verbatim. Verified by
diffing the original against the four files: the only changed lines are
the fourteen declarations that gained an export keyword.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Split dnr.ts along its three concerns
818 lines holding rule construction, the serialized sync state machine,
and the RE2 fitting and sharding, with `buildRules` at the top and
`fitPlan` five hundred lines below it. Nothing showed that those two are
entry points into one set of constructors rather than two copies of
them.
`dnr/rules.ts` is now the only module that mints a rule, and it has
exactly two consumers, both visible from its import graph: `buildRules`
beside it, which only tests call, and `fitPlan` in `dnr/fit.ts`, which
`syncRules` calls. `fit.ts` defines no rule of its own, so what a
`buildRules` test omits is precisely the fitting step, which the
docstrings now say outright. `dnr/keywords.ts` holds the ranking, the
alternation order and the sharding.
Every invariant comment travelled with its own code: the priority tiers,
the RE2 pattern that has to swallow the whole URL remainder, the two
orders one list rule, the fail-closed precondition, and the trailing
slot the serialized rebuild consults before the in-flight one. Verified
line by line against the original; the only additions are export
keywords.
The public surface is unchanged and no test needed an edit.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Split the browse route so its one rule can be checked by grep
842 lines, of which `renderBrowse` was 531 holding eight mutually
referencing closures over several mutable locals. The rule that
`applyFilter` is the only writer of visibility, of every count and of
the badge could only be verified by reading all of it, and two shipped
bugs lived there for exactly that reason.
`browse-row.ts` takes the row, which closed over nothing.
`browse-groups.ts` takes the group headings, the runs and the refiling
of a row between them. Neither writes anything that is on screen: the
headings and the bulk buttons are built empty, and every function that
changes what a group holds takes the repaint as a callback. So the rule
is now a grep over two short modules. `browse.ts` is 500 lines and no
longer imports the storage writers at all.
`browse-groups.ts` is plain functions over their arguments rather than
the factory the review suggested. A factory closed over the collapse
state and a repaint callback would have to be constructed before
`applyFilter` exists and then be read by it, which puts a mutable slot
on the one seam this contract lives on.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Give the browse view a DOM test suite, on jsdom
Around 3,400 lines of view code were untested by construction: vitest
runs under `environment: node` and there was no alternative, so two of
the three bugs the last review found were in code no test could reach.
jsdom joins the dev tooling, and exactly one suite opts into it with a
`// @vitest-environment jsdom` docblock. The global default stays
`node`, which is what keeps the rule that lib and model import cleanly
without a DOM able to fail.
The suite covers the Hidden shortcuts state machine, the newest code in
the repo: a switch moves the row between groups and repaints both
headings, a section survives losing its last live row, the group leaves
the page when its last row is switched on, a bulk action is one write
for the whole run, delete drops the row from every total, and the filter
force-expands the folded group to reveal a hidden row. Two assertions
were mutation-checked: moving the commit inside the bulk loop fails the
one-write test, and a bare collapse read fails the force-expand test.
The docstring is honest about the ceiling. jsdom does no layout, so
`focus()` inside a hidden subtree succeeds there and fails in Chrome,
which is precisely the bug this file cannot catch, and the CSS order
reordering is invisible to it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Delete 39 test cases that were covering something else's ground
The suite was 1401 cases from 776 written blocks. These four were
duplicates, and each was checked against the code before it went.
Three form-builder cases: the form's `buildCommand` is a four-line
wrapper whose only addition is narrowing the category, and the three
cases removed were asserting the wrapped builder's own behaviour, which
its own test file already covers more strictly.
Thirty-five self-interception cases: every sweep in that file ran twice,
once over the test-only `buildRules` and once over the rules the sync
path registers. Both sets were built over the shipped registry and
compared rule by rule: 36 rules each, identical in priority, action and
condition, differing only in id. The mirror was catching nothing.
Invariant 1 is untouched, and is now derived only from the rules that
actually ship, which is the stronger of the two.
One manifest-floor case asserted from the token tests what the manifest
test asserts more strictly. Its reasoning moved into the surviving
comment rather than being lost.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Add Prettier and ESLint, and put lint first in the gate
CONTRIBUTING stated the style rules by hand and nothing checked them, so
the first outside pull request was going to be a style negotiation in
review comments.
Prettier is configured from what the repo already does rather than from
its defaults. Every setting was measured: print width 100 is the value
that touches the fewest files and the fewest lines out of eleven
candidates, and trailing commas and arrow parens were chosen the same
way. Both stylesheets came through the first run unchanged, which is a
fair signal the config matches the house style. design/ is excluded
because it is review-gated and its hand-aligned contrast-ratio comments
do not survive a formatter, go.html because its inline style block is
deliberately minified on the one page whose job is to redirect before it
paints, and Markdown because a formatter has nothing to offer prose that
is already hand-wrapped.
ESLint is flat config and type-aware, which costs about two seconds, so
it runs first in CI as the fastest signal. It enforces the two rules a
typechecker cannot see and CONTRIBUTING already asked for: no default
exports, and `import type` for type-only imports. Every rule turned off
is a convention rather than a dodge, and each carries its reason in the
config. The largest is the unsafe-assignment rule, which fires on
exactly the null-prototype construction that exists to satisfy
invariant 17.
The one real suggestion it made is fixed here: the import parser now
attaches the underlying error as `cause` when it rethrows a JSON parse
failure, so the stack survives.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Sweep the dead exports and the comments that describe old approaches
Several passes of feature removal and three file splits landed in the
last day, each cleaning up after itself and each missing something. This
is the sweep, plus the repo-wide Prettier pass, which touched about four
and a half percent of the lines and changed no behaviour.
Fifteen exports dropped where nothing outside the file called them, so
`noUnusedLocals` keeps them honest from now on. No code deleted and
nothing renamed. Deliberate test-only seams were left alone, and so was
every exported type that names a public signature.
The comments were the important half. A confidently wrong comment is
worse than none, and this codebase comments heavily. Five referred to
"the monolith", a file layout that has not existed for a long time and
that a stranger has no way to look up; each now states the constraint
directly. Two pointed at a per-shortcut Restore that was removed. Two
named `weather`, `gimg` and `gsite` as the commands at risk of
self-interception, and none of those three still exists, so both were
rederived by running the current registry through the current rules.
Four pointed at modules the splits moved code out of. Two quoted
keyword and shard counts that were off by a factor. Four entries in the
token tests still described the dispatch toast and its dismiss button,
and those strings are interpolated into live test names.
No dead CSS was found. All 126 class selectors in the two sheets are
still rendered, checked in both directions.
One thing left as a finding rather than fixed: a sync-rules test named
for the loop URL that used to bounce forever now drives `weather boston`
through the fallback-engine path, because `weather` is not a command any
more. It still passes and still covers something, but not what its name
says. Pointing it at a command that does resolve onto an intercepted
engine is a behaviour decision, not a comment fix.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Turn on noUncheckedIndexedAccess and answer what it asks
The code indexes arrays constantly and guarded inconsistently: some
sites checked the first keyword before reading it, others read a run or
an escape plan by index with nothing checking the length. Every one was
correct by construction, and nothing was verifying that.
Nineteen sites under src/, and not one of them is a non-null assertion.
This codebase has no `any`, no ignores and no `!` anywhere in src/, and
that is worth more than the shortcut. The fixes are real: a length check
written in the form the compiler reads, a regex capture tested instead
of its match, a total API in place of an index, and two parallel arrays
restructured so the pairing cannot come apart at all.
Three sites were correct only because of a fact stated in another file,
and each is now local and commented. The sharpest is the escape-rule
precondition in the rule fitter: a missing escape rule would have thrown
inside the fitter, escaped into the sync, and left the fail-closed
branch tearing down the whole dynamic rule table. It now treats that
engine as refused, which is what invariant 2 already prescribes.
Five branches had to be chosen for cases that cannot arise today. Each
takes what the surrounding code does for the nearest case that can: a
keyless member drops out of a pack's sample rather than rendering
undefined into it, a missing row removes the active-descendant
attribute as the no-selection path does, and a character outside the
escape map is kept rather than dropped.
Under tests/, one helper that throws on a missing element, used
sixty-eight times. It never substitutes a default, so a test still fails
for the reason it was written to fail.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Cut the test suite to the 150 cases that would catch a broken build
1369 cases across 27 files, down to 150 across 20, running in half a
second. The question asked of every survivor was whether a user would
notice if it vanished and the code broke.
What went. Every design and token assertion, so nothing now enforces the
no-literal-hex and type-scale conventions but discipline. Every test
that asserted a removed feature stayed removed, which tests history
rather than behaviour. The view tests that were DOM assembly rather than
decisions, including the jsdom suite added yesterday: the decisions
under it are pure and still covered, and the parts that really break
need a browser that jsdom cannot be. jsdom leaves package.json with it,
since a dependency carrying no tests is worse than neither. The
source-text tests, which asserted what the code looked like rather than
what it did. And the sweeps: assertions run once per registry row are
now single property tests that name every row that drifted.
The seventeen invariants were the hard call, because AGENTS.md says
their regression tests must never be deleted and that now conflicts with
the instruction. Resolved by keeping, for each invariant whose failure a
user would meet, the one smallest test that goes red when the bug comes
back, with the comment saying which bug that is. Fifteen have one test.
Invariant 16 keeps two, because the edit path and the storage boundary
are different code and fixing one leaves the other red. Two have none,
and AGENTS.md now says so rather than implying cover it never had.
The surviving suite was checked by breaking the source three times: the
self-interception marker, the pattern that has to swallow Chrome's
appended parameters, and the edit that must copy named fields rather
than spread. Three, three and five failures respectively.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* docs: refresh README and add UI screenshots
* Remove the Web Store submission material
The crib and the store directory go, along with the listing copy and
the padded listing icon.
Four things referenced them and are updated rather than left dangling.
The README logo now points at the toolbar icon, which is tracked and
shipped, so the header still renders; it is the full-bleed art rather
than the padded tile, which is the one visible difference. The install
section no longer sends a reader to a file that is not there. The
release steps in CONTRIBUTING end at uploading the zip. The architecture
map drops both entries.
The icon generator no longer emits the padded 128px tile, since nothing
consumes it now, and the drift check in CI watches only public/icons.
Re-running the generator leaves the tracked icons byte-identical.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Drop the lead-in sentence above the README examples
The three examples read on their own, and the arrows already say what
the sentence was announcing.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>1 parent 70e10fa commit 1fd3af5
100 files changed
Lines changed: 4786 additions & 10250 deletions
File tree
- .github
- ISSUE_TEMPLATE
- workflows
- docs
- images
- extras/packs
- public
- scripts
- lib
- src
- go
- lib
- dnr
- storage
- options
- model
- views
- popup
- store
- tests
- helpers
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
38 | | - | |
39 | | - | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
40 | 41 | | |
41 | | - | |
| 42 | + | |
42 | 43 | | |
43 | 44 | | |
44 | 45 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
| 13 | + | |
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
| |||
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
28 | 33 | | |
29 | 34 | | |
30 | 35 | | |
31 | 36 | | |
32 | 37 | | |
33 | 38 | | |
34 | 39 | | |
35 | | - | |
| 40 | + | |
36 | 41 | | |
37 | 42 | | |
38 | 43 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
14 | | - | |
15 | | - | |
| 14 | + | |
16 | 15 | | |
17 | 16 | | |
18 | 17 | | |
| |||
83 | 82 | | |
84 | 83 | | |
85 | 84 | | |
86 | | - | |
87 | | - | |
88 | | - | |
89 | | - | |
90 | | - | |
91 | 85 | | |
92 | 86 | | |
93 | 87 | | |
94 | 88 | | |
95 | 89 | | |
96 | 90 | | |
97 | | - | |
98 | | - | |
99 | | - | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
100 | 99 | | |
101 | 100 | | |
102 | 101 | | |
| |||
117 | 116 | | |
118 | 117 | | |
119 | 118 | | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
120 | 122 | | |
121 | 123 | | |
122 | 124 | | |
123 | 125 | | |
124 | 126 | | |
125 | 127 | | |
126 | 128 | | |
127 | | - | |
128 | | - | |
| 129 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
7 | | - | |
8 | | - | |
9 | | - | |
10 | | - | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
11 | 14 | | |
12 | 15 | | |
13 | 16 | | |
| |||
26 | 29 | | |
27 | 30 | | |
28 | 31 | | |
29 | | - | |
| 32 | + | |
30 | 33 | | |
31 | 34 | | |
32 | | - | |
33 | | - | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
34 | 38 | | |
35 | 39 | | |
36 | 40 | | |
| |||
46 | 50 | | |
47 | 51 | | |
48 | 52 | | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
49 | 70 | | |
50 | 71 | | |
51 | 72 | | |
| |||
75 | 96 | | |
76 | 97 | | |
77 | 98 | | |
78 | | - | |
| 99 | + | |
| 100 | + | |
79 | 101 | | |
80 | 102 | | |
81 | 103 | | |
82 | 104 | | |
83 | 105 | | |
84 | 106 | | |
85 | | - | |
86 | | - | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
87 | 117 | | |
88 | 118 | | |
89 | 119 | | |
| |||
105 | 135 | | |
106 | 136 | | |
107 | 137 | | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
23 | 29 | | |
24 | 30 | | |
25 | 31 | | |
| |||
34 | 40 | | |
35 | 41 | | |
36 | 42 | | |
37 | | - | |
38 | | - | |
39 | | - | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
40 | 49 | | |
41 | 50 | | |
42 | 51 | | |
| |||
0 commit comments