github-mobile-reader 0.1.0 → 0.1.2
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.
- package/README.ko.md +585 -0
- package/README.md +157 -84
- package/dist/action.js +177 -30
- package/dist/cli.js +552 -0
- package/dist/index.d.mts +15 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.js +198 -23
- package/dist/index.mjs +188 -22
- package/package.json +7 -3
package/README.md
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# 📖 github-mobile-reader
|
|
2
2
|
|
|
3
|
-
> **Stop squinting at code on your phone.**
|
|
4
3
|
> `github-mobile-reader` transforms raw git diffs into clean, vertically-scrollable Markdown — no more pinch-zooming or swiping left and right to read a single line.
|
|
5
4
|
|
|
6
5
|
[](https://www.npmjs.com/package/github-mobile-reader)
|
|
@@ -15,15 +14,17 @@ GitHub's mobile web view renders code in a fixed-width monospace block. Long lin
|
|
|
15
14
|
|
|
16
15
|
## The Solution
|
|
17
16
|
|
|
18
|
-
`github-mobile-reader` parses a git diff and produces a **Logical Flow** — a compact tree that shows
|
|
17
|
+
`github-mobile-reader` parses a git diff and produces a **Logical Flow** — a compact tree that shows _what the code does_, not just what characters changed. The result is a Markdown document that reads top-to-bottom on any screen width.
|
|
19
18
|
|
|
20
19
|
**Before** (raw diff, mobile web):
|
|
20
|
+
|
|
21
21
|
```
|
|
22
22
|
← swipe → swipe → swipe →
|
|
23
23
|
+ const result = data.map(item => item.value).filter(v => v > 10).reduce((a,b) => a+b, 0)
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
**After** (Reader Markdown):
|
|
27
|
+
|
|
27
28
|
```
|
|
28
29
|
data
|
|
29
30
|
└─ map(item → value)
|
|
@@ -37,9 +38,13 @@ data
|
|
|
37
38
|
|
|
38
39
|
- **Zero-dependency core** — the parser runs anywhere Node.js ≥ 18 is available
|
|
39
40
|
- **Dual output format** — CJS (`require`) and ESM (`import`) with full TypeScript types
|
|
41
|
+
- **CLI** — `npx github-mobile-reader --repo owner/repo --pr 42` fetches and converts any PR instantly
|
|
40
42
|
- **GitHub Action** — drop one YAML block into any repo and get auto-generated Reader docs on every PR
|
|
41
|
-
- **
|
|
43
|
+
- **File-by-file output** — each changed JS/TS file gets its own independent section in the output
|
|
44
|
+
- **JSX/Tailwind aware** — `.jsx`/`.tsx` files get a component tree (`🎨 JSX Structure`) and a Tailwind class diff (`💅 Style Changes`) instead of one unreadable blob
|
|
45
|
+
- **Tracks both sides of a diff** — shows added _and_ removed code in separate sections
|
|
42
46
|
- **Conservative by design** — when a pattern is ambiguous, the library shows less rather than showing something wrong
|
|
47
|
+
- **Secure by default** — token is read from `$GITHUB_TOKEN` only; no flag that leaks to shell history or `ps`
|
|
43
48
|
|
|
44
49
|
---
|
|
45
50
|
|
|
@@ -47,13 +52,14 @@ data
|
|
|
47
52
|
|
|
48
53
|
1. [Quick Start](#quick-start)
|
|
49
54
|
2. [Language Support](#language-support)
|
|
50
|
-
3. [
|
|
51
|
-
4. [
|
|
52
|
-
5. [
|
|
53
|
-
6. [
|
|
54
|
-
7. [
|
|
55
|
-
8. [
|
|
56
|
-
9. [
|
|
55
|
+
3. [CLI Usage](#cli-usage)
|
|
56
|
+
4. [GitHub Action (recommended)](#github-action-recommended)
|
|
57
|
+
5. [npm Library Usage](#npm-library-usage)
|
|
58
|
+
6. [Output Format](#output-format)
|
|
59
|
+
7. [API Reference](#api-reference)
|
|
60
|
+
8. [How the Parser Works](#how-the-parser-works)
|
|
61
|
+
9. [Contributing](#contributing)
|
|
62
|
+
10. [License](#license)
|
|
57
63
|
|
|
58
64
|
---
|
|
59
65
|
|
|
@@ -63,17 +69,17 @@ The parser is built on regex-based pattern matching, so it can technically recei
|
|
|
63
69
|
|
|
64
70
|
### Current support (v0.1)
|
|
65
71
|
|
|
66
|
-
| Language
|
|
67
|
-
|
|
68
|
-
| **JavaScript**
|
|
69
|
-
| **TypeScript**
|
|
70
|
-
| **React JSX**
|
|
71
|
-
| **React TSX**
|
|
72
|
-
| **Next.js**
|
|
73
|
-
| **Java**
|
|
74
|
-
| **C#**
|
|
75
|
-
| **C**
|
|
76
|
-
| **Python, Go, Rust, etc.** | —
|
|
72
|
+
| Language | Extensions | Flow Quality | Notes |
|
|
73
|
+
| -------------------------- | ------------------------- | :---------------: | --------------------------------------------------------------------------------------- |
|
|
74
|
+
| **JavaScript** | `.js` `.mjs` `.cjs` | ✅ Full | Baseline target language |
|
|
75
|
+
| **TypeScript** | `.ts` | ✅ Full | JS superset — all patterns apply |
|
|
76
|
+
| **React JSX** | `.jsx` | ✅ Full | Same syntax as JS |
|
|
77
|
+
| **React TSX** | `.tsx` | ✅ Full | Same syntax as TS |
|
|
78
|
+
| **Next.js** | `.js` `.ts` `.jsx` `.tsx` | ✅ Full | Framework on top of JS/TS |
|
|
79
|
+
| **Java** | `.java` | ⚠️ Partial (~55%) | `if/for/while` and dot-chaining work; function declarations missed (no `const/let/var`) |
|
|
80
|
+
| **C#** | `.cs` | ⚠️ Partial (~35%) | LINQ chaining (`.Where().Select()`) works; `using`/`namespace`/`class` not detected |
|
|
81
|
+
| **C** | `.c` `.h` | ❌ Minimal (~15%) | No matching keywords; pointer syntax (`->`, `*`) not understood |
|
|
82
|
+
| **Python, Go, Rust, etc.** | — | 🔜 Planned | See roadmap below |
|
|
77
83
|
|
|
78
84
|
> **Note:** Java, C#, and C files are not processed by the GitHub Action by default.
|
|
79
85
|
> The Action only scans `.js .jsx .ts .tsx .mjs .cjs` files ([`src/action.ts` line 66](src/action.ts)).
|
|
@@ -86,8 +92,8 @@ All four share the same underlying syntax. The parser recognises:
|
|
|
86
92
|
- **Method chaining** — line starting with `.` after a line ending with `)` or `}`
|
|
87
93
|
```ts
|
|
88
94
|
data
|
|
89
|
-
.filter(item => item.active)
|
|
90
|
-
.map(item => item.value)
|
|
95
|
+
.filter((item) => item.active) // detected as P1 chain
|
|
96
|
+
.map((item) => item.value); // detected as P1 chain
|
|
91
97
|
```
|
|
92
98
|
- **Function declarations** — `const`, `let`, `var`, `function`, `async`
|
|
93
99
|
- **Conditionals** — `if / else / switch`
|
|
@@ -98,12 +104,12 @@ All four share the same underlying syntax. The parser recognises:
|
|
|
98
104
|
|
|
99
105
|
These languages use different conventions for the patterns above:
|
|
100
106
|
|
|
101
|
-
| Concept
|
|
102
|
-
|
|
103
|
-
| Variable declaration | `const x = …`
|
|
104
|
-
| Arrow callbacks
|
|
105
|
-
| Noise imports
|
|
106
|
-
| Async functions
|
|
107
|
+
| Concept | JS/TS (✅ detected) | Java / C# / C (❌ missed) |
|
|
108
|
+
| -------------------- | ---------------------- | -------------------------------- |
|
|
109
|
+
| Variable declaration | `const x = …` | `int x = …` / `String x = …` |
|
|
110
|
+
| Arrow callbacks | `x => x.value` | Lambdas differ per language |
|
|
111
|
+
| Noise imports | `import` / `export` | `using` / `#include` / `package` |
|
|
112
|
+
| Async functions | `async function foo()` | `async Task<T> Foo()` |
|
|
107
113
|
|
|
108
114
|
### Roadmap — Language Adapter system (v0.2)
|
|
109
115
|
|
|
@@ -118,6 +124,7 @@ src/languages/
|
|
|
118
124
|
```
|
|
119
125
|
|
|
120
126
|
Each adapter will declare:
|
|
127
|
+
|
|
121
128
|
- Supported file extensions
|
|
122
129
|
- Function-declaration detection pattern
|
|
123
130
|
- Keywords to ignore (noise list)
|
|
@@ -127,6 +134,67 @@ If you'd like to contribute an adapter for your language, see [Contributing](#co
|
|
|
127
134
|
|
|
128
135
|
---
|
|
129
136
|
|
|
137
|
+
## CLI Usage
|
|
138
|
+
|
|
139
|
+
Run `github-mobile-reader` directly from your terminal — no setup, no config file. It fetches a PR diff from GitHub, converts it to mobile-friendly Markdown, and saves one file per PR to `./reader-output/`.
|
|
140
|
+
|
|
141
|
+
### Authentication
|
|
142
|
+
|
|
143
|
+
Set your GitHub token as an environment variable **before** running the CLI:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
export GITHUB_TOKEN=ghp_xxxx
|
|
147
|
+
npx github-mobile-reader --repo owner/repo --pr 42
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
> **Security note:** The CLI does not accept a `--token` flag. Passing secrets as command-line arguments exposes them in shell history and `ps` output. Always use the environment variable.
|
|
151
|
+
|
|
152
|
+
### Single PR
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
npx github-mobile-reader --repo owner/repo --pr 42
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### All recent PRs
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
npx github-mobile-reader --repo owner/repo --all
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Options
|
|
165
|
+
|
|
166
|
+
| Flag | Default | Description |
|
|
167
|
+
| --------- | ----------------- | ------------------------------------------------- |
|
|
168
|
+
| `--repo` | *(required)* | Repository in `owner/repo` format |
|
|
169
|
+
| `--pr` | — | Process a single PR by number |
|
|
170
|
+
| `--all` | — | Process all recent PRs (use with `--limit`) |
|
|
171
|
+
| `--out` | `./reader-output` | Output directory — relative paths only, no `..` |
|
|
172
|
+
| `--limit` | `10` | Max number of PRs to fetch when using `--all` |
|
|
173
|
+
|
|
174
|
+
Token: read from `$GITHUB_TOKEN` environment variable (60 req/hr unauthenticated, 5 000 req/hr authenticated).
|
|
175
|
+
|
|
176
|
+
### Output
|
|
177
|
+
|
|
178
|
+
Each PR produces one file: `reader-output/pr-<number>.md`.
|
|
179
|
+
|
|
180
|
+
Inside that file, every changed JS/TS file gets its own section. JSX/TSX files get two extra sections:
|
|
181
|
+
|
|
182
|
+
```
|
|
183
|
+
# 📖 PR #42 — My Feature
|
|
184
|
+
|
|
185
|
+
## 📄 `src/App.tsx`
|
|
186
|
+
|
|
187
|
+
### 🧠 Logical Flow ← JS logic tree
|
|
188
|
+
### 🎨 JSX Structure ← component hierarchy (JSX/TSX only)
|
|
189
|
+
### 💅 Style Changes ← added/removed Tailwind classes (JSX/TSX only)
|
|
190
|
+
### ✅ Added Code
|
|
191
|
+
### ❌ Removed Code
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
> **Note:** `reader-output/` is gitignored by default — the generated files are local only and not committed to your repository.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
130
198
|
## Quick Start
|
|
131
199
|
|
|
132
200
|
```bash
|
|
@@ -134,13 +202,13 @@ npm install github-mobile-reader
|
|
|
134
202
|
```
|
|
135
203
|
|
|
136
204
|
```ts
|
|
137
|
-
import { generateReaderMarkdown } from
|
|
138
|
-
import { execSync } from
|
|
205
|
+
import { generateReaderMarkdown } from "github-mobile-reader";
|
|
206
|
+
import { execSync } from "child_process";
|
|
139
207
|
|
|
140
|
-
const diff = execSync(
|
|
141
|
-
const markdown = generateReaderMarkdown(diff, { file:
|
|
208
|
+
const diff = execSync("git diff HEAD~1", { encoding: "utf8" });
|
|
209
|
+
const markdown = generateReaderMarkdown(diff, { file: "src/utils.ts" });
|
|
142
210
|
|
|
143
|
-
console.log(markdown)
|
|
211
|
+
console.log(markdown);
|
|
144
212
|
```
|
|
145
213
|
|
|
146
214
|
---
|
|
@@ -165,8 +233,8 @@ on:
|
|
|
165
233
|
types: [opened, synchronize, reopened]
|
|
166
234
|
|
|
167
235
|
permissions:
|
|
168
|
-
contents: write
|
|
169
|
-
pull-requests: write
|
|
236
|
+
contents: write # commit the generated .md file
|
|
237
|
+
pull-requests: write # post the PR comment
|
|
170
238
|
|
|
171
239
|
jobs:
|
|
172
240
|
generate-reader:
|
|
@@ -177,7 +245,7 @@ jobs:
|
|
|
177
245
|
- name: Checkout
|
|
178
246
|
uses: actions/checkout@v4
|
|
179
247
|
with:
|
|
180
|
-
fetch-depth: 0
|
|
248
|
+
fetch-depth: 0 # full history required for git diff
|
|
181
249
|
|
|
182
250
|
- name: Generate Reader Markdown
|
|
183
251
|
uses: 3rdflr/github-mobile-reader@v1
|
|
@@ -210,11 +278,11 @@ That's it. Every subsequent PR will automatically get:
|
|
|
210
278
|
|
|
211
279
|
### Action Inputs
|
|
212
280
|
|
|
213
|
-
| Input
|
|
214
|
-
|
|
215
|
-
| `github_token` | ✅
|
|
216
|
-
| `base_branch`
|
|
217
|
-
| `output_dir`
|
|
281
|
+
| Input | Required | Default | Description |
|
|
282
|
+
| -------------- | -------- | ------------- | ----------------------------------- |
|
|
283
|
+
| `github_token` | ✅ | — | Use `${{ secrets.GITHUB_TOKEN }}` |
|
|
284
|
+
| `base_branch` | ❌ | `main` | The branch the PR is merging into |
|
|
285
|
+
| `output_dir` | ❌ | `docs/reader` | Directory for generated `.md` files |
|
|
218
286
|
|
|
219
287
|
---
|
|
220
288
|
|
|
@@ -238,35 +306,38 @@ yarn add github-mobile-reader
|
|
|
238
306
|
### CommonJS
|
|
239
307
|
|
|
240
308
|
```js
|
|
241
|
-
const { generateReaderMarkdown } = require(
|
|
309
|
+
const { generateReaderMarkdown } = require("github-mobile-reader");
|
|
242
310
|
```
|
|
243
311
|
|
|
244
312
|
### ESM / TypeScript
|
|
245
313
|
|
|
246
314
|
```ts
|
|
247
|
-
import {
|
|
315
|
+
import {
|
|
316
|
+
generateReaderMarkdown,
|
|
317
|
+
parseDiffToLogicalFlow,
|
|
318
|
+
} from "github-mobile-reader";
|
|
248
319
|
```
|
|
249
320
|
|
|
250
321
|
### Basic Example
|
|
251
322
|
|
|
252
323
|
```ts
|
|
253
|
-
import { generateReaderMarkdown } from
|
|
254
|
-
import { execSync } from
|
|
255
|
-
import { writeFileSync } from
|
|
324
|
+
import { generateReaderMarkdown } from "github-mobile-reader";
|
|
325
|
+
import { execSync } from "child_process";
|
|
326
|
+
import { writeFileSync } from "fs";
|
|
256
327
|
|
|
257
328
|
// Get the diff for the last commit
|
|
258
|
-
const diff = execSync(
|
|
329
|
+
const diff = execSync("git diff HEAD~1 HEAD", { encoding: "utf8" });
|
|
259
330
|
|
|
260
331
|
// Generate Reader Markdown with metadata
|
|
261
332
|
const markdown = generateReaderMarkdown(diff, {
|
|
262
|
-
pr:
|
|
263
|
-
commit:
|
|
264
|
-
file:
|
|
265
|
-
repo:
|
|
266
|
-
})
|
|
333
|
+
pr: "42",
|
|
334
|
+
commit: "a1b2c3d",
|
|
335
|
+
file: "src/api/users.ts",
|
|
336
|
+
repo: "my-org/my-repo",
|
|
337
|
+
});
|
|
267
338
|
|
|
268
339
|
// Write to a file or post to Slack / Discord / GitHub
|
|
269
|
-
writeFileSync(
|
|
340
|
+
writeFileSync("reader.md", markdown, "utf8");
|
|
270
341
|
```
|
|
271
342
|
|
|
272
343
|
### Low-level API Example
|
|
@@ -274,16 +345,16 @@ writeFileSync('reader.md', markdown, 'utf8')
|
|
|
274
345
|
If you only need the parsed tree (e.g. to build your own renderer):
|
|
275
346
|
|
|
276
347
|
```ts
|
|
277
|
-
import { parseDiffToLogicalFlow, renderFlowTree } from
|
|
348
|
+
import { parseDiffToLogicalFlow, renderFlowTree } from "github-mobile-reader";
|
|
278
349
|
|
|
279
|
-
const { root, rawCode, removedCode } = parseDiffToLogicalFlow(diff)
|
|
350
|
+
const { root, rawCode, removedCode } = parseDiffToLogicalFlow(diff);
|
|
280
351
|
|
|
281
352
|
// root → FlowNode[] (the logical tree)
|
|
282
353
|
// rawCode → string (added lines, joined)
|
|
283
354
|
// removedCode → string (removed lines, joined)
|
|
284
355
|
|
|
285
|
-
const treeLines = renderFlowTree(root)
|
|
286
|
-
console.log(treeLines.join(
|
|
356
|
+
const treeLines = renderFlowTree(root);
|
|
357
|
+
console.log(treeLines.join("\n"));
|
|
287
358
|
```
|
|
288
359
|
|
|
289
360
|
---
|
|
@@ -304,13 +375,14 @@ A generated Reader Markdown document has four sections:
|
|
|
304
375
|
---
|
|
305
376
|
|
|
306
377
|
## 🧠 Logical Flow
|
|
307
|
-
|
|
308
378
|
```
|
|
379
|
+
|
|
309
380
|
getData()
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
381
|
+
└─ filter(callback)
|
|
382
|
+
└─ map(item → value)
|
|
383
|
+
└─ reduce(callback)
|
|
384
|
+
|
|
385
|
+
````
|
|
314
386
|
|
|
315
387
|
## ✅ Added Code
|
|
316
388
|
|
|
@@ -319,17 +391,19 @@ const result = getData()
|
|
|
319
391
|
.filter(item => item.active)
|
|
320
392
|
.map(item => item.value)
|
|
321
393
|
.reduce((a, b) => a + b, 0)
|
|
322
|
-
|
|
394
|
+
````
|
|
323
395
|
|
|
324
396
|
## ❌ Removed Code
|
|
325
397
|
|
|
326
398
|
```typescript
|
|
327
|
-
const result = getData().map(item => item.value)
|
|
399
|
+
const result = getData().map((item) => item.value);
|
|
328
400
|
```
|
|
329
401
|
|
|
330
402
|
---
|
|
403
|
+
|
|
331
404
|
🛠 Auto-generated by github-mobile-reader. Do not edit manually.
|
|
332
|
-
|
|
405
|
+
|
|
406
|
+
````
|
|
333
407
|
|
|
334
408
|
---
|
|
335
409
|
|
|
@@ -363,7 +437,7 @@ interface ParseResult {
|
|
|
363
437
|
rawCode: string // added lines joined with \n
|
|
364
438
|
removedCode: string // removed lines joined with \n
|
|
365
439
|
}
|
|
366
|
-
|
|
440
|
+
````
|
|
367
441
|
|
|
368
442
|
---
|
|
369
443
|
|
|
@@ -372,7 +446,7 @@ interface ParseResult {
|
|
|
372
446
|
Converts a `FlowNode[]` tree into an array of Markdown-safe text lines.
|
|
373
447
|
|
|
374
448
|
```ts
|
|
375
|
-
const lines = renderFlowTree(root)
|
|
449
|
+
const lines = renderFlowTree(root);
|
|
376
450
|
// [ 'getData()', ' └─ filter(callback)', ' └─ map(item → value)' ]
|
|
377
451
|
```
|
|
378
452
|
|
|
@@ -382,11 +456,11 @@ const lines = renderFlowTree(root)
|
|
|
382
456
|
|
|
383
457
|
```ts
|
|
384
458
|
interface FlowNode {
|
|
385
|
-
type:
|
|
386
|
-
name: string
|
|
387
|
-
children: FlowNode[]
|
|
388
|
-
depth: number
|
|
389
|
-
priority: Priority
|
|
459
|
+
type: "root" | "chain" | "condition" | "loop" | "function" | "call";
|
|
460
|
+
name: string;
|
|
461
|
+
children: FlowNode[];
|
|
462
|
+
depth: number;
|
|
463
|
+
priority: Priority;
|
|
390
464
|
}
|
|
391
465
|
```
|
|
392
466
|
|
|
@@ -394,13 +468,13 @@ interface FlowNode {
|
|
|
394
468
|
|
|
395
469
|
### `Priority` (enum)
|
|
396
470
|
|
|
397
|
-
| Value
|
|
398
|
-
|
|
399
|
-
| `CHAINING = 1`
|
|
400
|
-
| `CONDITIONAL = 2` | `if` / `else` / `switch` blocks
|
|
401
|
-
| `LOOP = 3`
|
|
402
|
-
| `FUNCTION = 4`
|
|
403
|
-
| `OTHER = 5`
|
|
471
|
+
| Value | Meaning |
|
|
472
|
+
| ----------------- | ----------------------------------------------------------- |
|
|
473
|
+
| `CHAINING = 1` | Method chains (`.map()`, `.filter()`, …) — highest priority |
|
|
474
|
+
| `CONDITIONAL = 2` | `if` / `else` / `switch` blocks |
|
|
475
|
+
| `LOOP = 3` | `for` / `while` loops |
|
|
476
|
+
| `FUNCTION = 4` | Function declarations |
|
|
477
|
+
| `OTHER = 5` | Everything else |
|
|
404
478
|
|
|
405
479
|
---
|
|
406
480
|
|
|
@@ -474,8 +548,10 @@ github-mobile-reader/
|
|
|
474
548
|
├── src/
|
|
475
549
|
│ ├── parser.ts ← core diff → logical flow parser
|
|
476
550
|
│ ├── index.ts ← public npm API surface
|
|
477
|
-
│
|
|
551
|
+
│ ├── action.ts ← GitHub Action entry point
|
|
552
|
+
│ └── cli.ts ← CLI entry point (npx github-mobile-reader)
|
|
478
553
|
├── dist/ ← compiled output (auto-generated, do not edit)
|
|
554
|
+
├── reader-output/ ← CLI output directory (gitignored)
|
|
479
555
|
├── .github/
|
|
480
556
|
│ └── workflows/
|
|
481
557
|
│ └── mobile-reader.yml ← example workflow for consumers
|
|
@@ -499,6 +575,3 @@ The parser currently relies on JS/TS syntax heuristics (dot-chaining, `const`/`l
|
|
|
499
575
|
MIT © [3rdflr](https://github.com/3rdflr)
|
|
500
576
|
|
|
501
577
|
---
|
|
502
|
-
|
|
503
|
-
> **"The era of per-device number crunching is over.
|
|
504
|
-
> One logic. Every screen."**
|