github-mobile-reader 0.1.2 → 0.1.4
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 +74 -65
- package/README.md +73 -66
- package/dist/action.js +72 -188
- package/dist/cli.js +74 -189
- package/dist/index.d.mts +15 -2
- package/dist/index.d.ts +15 -2
- package/dist/index.js +85 -35
- package/dist/index.mjs +83 -35
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -11,7 +11,9 @@ function isJSXFile(filename) {
|
|
|
11
11
|
return /\.(jsx|tsx)$/.test(filename);
|
|
12
12
|
}
|
|
13
13
|
function hasJSXContent(lines) {
|
|
14
|
-
return lines.some(
|
|
14
|
+
return lines.some(
|
|
15
|
+
(l) => /<[A-Z][A-Za-z]*[\s/>]/.test(l) || /return\s*\(/.test(l)
|
|
16
|
+
);
|
|
15
17
|
}
|
|
16
18
|
function isClassNameOnlyLine(line) {
|
|
17
19
|
return /^className=/.test(line.trim());
|
|
@@ -19,7 +21,9 @@ function isClassNameOnlyLine(line) {
|
|
|
19
21
|
function extractClassName(line) {
|
|
20
22
|
const staticMatch = line.match(/className="([^"]*)"/);
|
|
21
23
|
if (staticMatch) return staticMatch[1];
|
|
22
|
-
const ternaryMatch = line.match(
|
|
24
|
+
const ternaryMatch = line.match(
|
|
25
|
+
/className=\{[^?]+\?\s*"([^"]*)"\s*:\s*"([^"]*)"\}/
|
|
26
|
+
);
|
|
23
27
|
if (ternaryMatch) return `${ternaryMatch[1]} ${ternaryMatch[2]}`;
|
|
24
28
|
const templateMatch = line.match(/className=\{`([^`]*)`\}/);
|
|
25
29
|
if (templateMatch) {
|
|
@@ -41,18 +45,21 @@ function parseClassNameChanges(addedLines, removedLines) {
|
|
|
41
45
|
const cls = extractClassName(line);
|
|
42
46
|
const comp = extractComponentFromLine(line);
|
|
43
47
|
if (!cls) continue;
|
|
44
|
-
if (!componentMap.has(comp))
|
|
48
|
+
if (!componentMap.has(comp))
|
|
49
|
+
componentMap.set(comp, { added: /* @__PURE__ */ new Set(), removed: /* @__PURE__ */ new Set() });
|
|
45
50
|
cls.split(/\s+/).filter(Boolean).forEach((c) => componentMap.get(comp).added.add(c));
|
|
46
51
|
}
|
|
47
52
|
for (const line of removedLines.filter((l) => /className=/.test(l))) {
|
|
48
53
|
const cls = extractClassName(line);
|
|
49
54
|
const comp = extractComponentFromLine(line);
|
|
50
55
|
if (!cls) continue;
|
|
51
|
-
if (!componentMap.has(comp))
|
|
56
|
+
if (!componentMap.has(comp))
|
|
57
|
+
componentMap.set(comp, { added: /* @__PURE__ */ new Set(), removed: /* @__PURE__ */ new Set() });
|
|
52
58
|
cls.split(/\s+/).filter(Boolean).forEach((c) => componentMap.get(comp).removed.add(c));
|
|
53
59
|
}
|
|
54
60
|
const changes = [];
|
|
55
61
|
for (const [comp, { added, removed }] of componentMap) {
|
|
62
|
+
if (comp === "unknown") continue;
|
|
56
63
|
const pureAdded = [...added].filter((c) => !removed.has(c));
|
|
57
64
|
const pureRemoved = [...removed].filter((c) => !added.has(c));
|
|
58
65
|
if (pureAdded.length === 0 && pureRemoved.length === 0) continue;
|
|
@@ -65,7 +72,8 @@ function renderStyleChanges(changes) {
|
|
|
65
72
|
for (const change of changes) {
|
|
66
73
|
lines.push(`**${change.component}**`);
|
|
67
74
|
if (change.added.length > 0) lines.push(` + ${change.added.join(" ")}`);
|
|
68
|
-
if (change.removed.length > 0)
|
|
75
|
+
if (change.removed.length > 0)
|
|
76
|
+
lines.push(` - ${change.removed.join(" ")}`);
|
|
69
77
|
}
|
|
70
78
|
return lines;
|
|
71
79
|
}
|
|
@@ -134,8 +142,12 @@ function parseJSXToFlowTree(lines) {
|
|
|
134
142
|
}
|
|
135
143
|
function filterDiffLines(diffText) {
|
|
136
144
|
const lines = diffText.split("\n");
|
|
137
|
-
const added = lines.filter(
|
|
138
|
-
|
|
145
|
+
const added = lines.filter(
|
|
146
|
+
(l) => l.startsWith("+") && !l.startsWith("+++") && l.trim() !== "+"
|
|
147
|
+
).map((l) => l.substring(1));
|
|
148
|
+
const removed = lines.filter(
|
|
149
|
+
(l) => l.startsWith("-") && !l.startsWith("---") && l.trim() !== "-"
|
|
150
|
+
).map((l) => l.substring(1));
|
|
139
151
|
return { added, removed };
|
|
140
152
|
}
|
|
141
153
|
function normalizeCode(lines) {
|
|
@@ -315,21 +327,63 @@ function parseDiffToLogicalFlow(diffText) {
|
|
|
315
327
|
removedCode: removed.join("\n")
|
|
316
328
|
};
|
|
317
329
|
}
|
|
330
|
+
function extractChangedSymbols(addedLines, removedLines) {
|
|
331
|
+
const FUNC_RE = /^(?:export\s+)?(?:async\s+)?function\s+([a-z]\w+)|^(?:export\s+)?(?:const|let|var)\s+([a-z]\w+)\s*=\s*(?:async\s+)?\(?|^(?:export\s+)?(?:const|let|var)\s+([a-z]\w+)\s*=\s*[a-z]\w+\s*[<(]/;
|
|
332
|
+
const COMPONENT_RE = /^(?:export\s+)?(?:default\s+)?(?:function|const)\s+([A-Z][a-z][A-Za-z0-9]*)/;
|
|
333
|
+
const extract = (lines) => {
|
|
334
|
+
const names = /* @__PURE__ */ new Set();
|
|
335
|
+
for (const line of lines) {
|
|
336
|
+
const cm = line.match(COMPONENT_RE) || line.match(FUNC_RE);
|
|
337
|
+
if (cm) {
|
|
338
|
+
const name = cm[1] || cm[2] || cm[3];
|
|
339
|
+
if (name) names.add(name);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
return names;
|
|
343
|
+
};
|
|
344
|
+
const addedNames = extract(addedLines);
|
|
345
|
+
const removedNames = extract(removedLines);
|
|
346
|
+
const results = [];
|
|
347
|
+
const seen = /* @__PURE__ */ new Set();
|
|
348
|
+
for (const name of addedNames) {
|
|
349
|
+
seen.add(name);
|
|
350
|
+
results.push({
|
|
351
|
+
name,
|
|
352
|
+
status: removedNames.has(name) ? "modified" : "added"
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
for (const name of removedNames) {
|
|
356
|
+
if (!seen.has(name)) {
|
|
357
|
+
results.push({ name, status: "removed" });
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return results;
|
|
361
|
+
}
|
|
362
|
+
function renderJSXTreeCompact(nodes, maxDepth = 3) {
|
|
363
|
+
const lines = [];
|
|
364
|
+
function walk(node, depth) {
|
|
365
|
+
if (depth > maxDepth) return;
|
|
366
|
+
const indent = " ".repeat(depth);
|
|
367
|
+
const hasChildren = node.children.length > 0;
|
|
368
|
+
lines.push(`${indent}${node.name}${hasChildren ? "" : ""}`);
|
|
369
|
+
for (const child of node.children) {
|
|
370
|
+
walk(child, depth + 1);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
for (const root of nodes) {
|
|
374
|
+
walk(root, 0);
|
|
375
|
+
}
|
|
376
|
+
return lines.join("\n");
|
|
377
|
+
}
|
|
318
378
|
function generateReaderMarkdown(diffText, meta = {}) {
|
|
319
379
|
const { added, removed } = filterDiffLines(diffText);
|
|
320
380
|
const isJSX = Boolean(
|
|
321
381
|
meta.file && isJSXFile(meta.file) || hasJSXContent(added)
|
|
322
382
|
);
|
|
323
|
-
const
|
|
324
|
-
const normalizedAdded = normalizeCode(addedForFlow);
|
|
325
|
-
const flowTree = parseToFlowTree(normalizedAdded);
|
|
326
|
-
const rawCode = addedForFlow.join("\n");
|
|
327
|
-
const removedForCode = isJSX ? removed.filter((l) => !isClassNameOnlyLine(l)) : removed;
|
|
328
|
-
const removedCode = removedForCode.join("\n");
|
|
383
|
+
const changedSymbols = extractChangedSymbols(added, removed);
|
|
329
384
|
const classNameChanges = isJSX ? parseClassNameChanges(added, removed) : [];
|
|
330
385
|
const jsxTree = isJSX ? parseJSXToFlowTree(added) : [];
|
|
331
386
|
const sections = [];
|
|
332
|
-
const lang = isJSX ? "tsx" : "typescript";
|
|
333
387
|
sections.push("# \u{1F4D6} GitHub Reader View\n");
|
|
334
388
|
sections.push("> Generated by **github-mobile-reader**");
|
|
335
389
|
if (meta.repo) sections.push(`> Repository: ${meta.repo}`);
|
|
@@ -337,41 +391,34 @@ function generateReaderMarkdown(diffText, meta = {}) {
|
|
|
337
391
|
if (meta.commit) sections.push(`> Commit: \`${meta.commit}\``);
|
|
338
392
|
if (meta.file) sections.push(`> File: \`${meta.file}\``);
|
|
339
393
|
sections.push("\n");
|
|
340
|
-
if (
|
|
341
|
-
sections.push("
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
394
|
+
if (changedSymbols.length > 0) {
|
|
395
|
+
sections.push("### \uBCC0\uACBD\uB41C \uD568\uC218 / \uCEF4\uD3EC\uB10C\uD2B8\n");
|
|
396
|
+
const STATUS_ICON = { added: "\u2705", removed: "\u274C", modified: "\u270F\uFE0F" };
|
|
397
|
+
for (const { name, status } of changedSymbols) {
|
|
398
|
+
sections.push(`- ${STATUS_ICON[status]} \`${name}()\` \u2014 ${status}`);
|
|
399
|
+
}
|
|
400
|
+
sections.push("");
|
|
345
401
|
}
|
|
346
402
|
if (isJSX && jsxTree.length > 0) {
|
|
347
|
-
sections.push("
|
|
403
|
+
sections.push("### \u{1F3A8} JSX Structure\n");
|
|
348
404
|
sections.push("```");
|
|
349
|
-
sections.push(
|
|
405
|
+
sections.push(renderJSXTreeCompact(jsxTree));
|
|
350
406
|
sections.push("```\n");
|
|
351
407
|
}
|
|
352
408
|
if (isJSX && classNameChanges.length > 0) {
|
|
353
|
-
sections.push("
|
|
409
|
+
sections.push("### \u{1F485} Style Changes\n");
|
|
354
410
|
sections.push(...renderStyleChanges(classNameChanges));
|
|
355
411
|
sections.push("");
|
|
356
412
|
}
|
|
357
|
-
if (rawCode.trim()) {
|
|
358
|
-
sections.push("## \u2705 Added Code\n");
|
|
359
|
-
sections.push(`\`\`\`${lang}`);
|
|
360
|
-
sections.push(rawCode);
|
|
361
|
-
sections.push("```\n");
|
|
362
|
-
}
|
|
363
|
-
if (removedCode.trim()) {
|
|
364
|
-
sections.push("## \u274C Removed Code\n");
|
|
365
|
-
sections.push(`\`\`\`${lang}`);
|
|
366
|
-
sections.push(removedCode);
|
|
367
|
-
sections.push("```\n");
|
|
368
|
-
}
|
|
369
413
|
sections.push("---");
|
|
370
|
-
sections.push(
|
|
414
|
+
sections.push(
|
|
415
|
+
"\u{1F6E0} Auto-generated by [github-mobile-reader](https://github.com/3rdflr/github-mobile-reader). Do not edit manually."
|
|
416
|
+
);
|
|
371
417
|
return sections.join("\n");
|
|
372
418
|
}
|
|
373
419
|
export {
|
|
374
420
|
Priority,
|
|
421
|
+
extractChangedSymbols,
|
|
375
422
|
extractClassName,
|
|
376
423
|
extractJSXComponentName,
|
|
377
424
|
filterDiffLines,
|
|
@@ -386,5 +433,6 @@ export {
|
|
|
386
433
|
parseJSXToFlowTree,
|
|
387
434
|
parseToFlowTree,
|
|
388
435
|
renderFlowTree,
|
|
436
|
+
renderJSXTreeCompact,
|
|
389
437
|
renderStyleChanges
|
|
390
438
|
};
|
package/package.json
CHANGED