@t8/docsgen 0.3.31 → 0.3.33
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/dist/bin.js +357 -304
- package/dist/css/base.css +2 -2
- package/dist/css/index.css +1 -7
- package/package.json +1 -1
- package/src/bin/content/createDirs.ts +21 -0
- package/src/bin/content/getCSSRoot.ts +44 -0
- package/src/bin/{getCounterContent.ts → content/getCounterContent.ts} +1 -1
- package/src/bin/content/getDefaultCodeStyleContent.ts +9 -0
- package/src/bin/{getIcon.ts → content/getIcon.ts} +1 -1
- package/src/bin/content/getIconTag.ts +10 -0
- package/src/bin/content/getIndexContent.ts +119 -0
- package/src/bin/{getInjectedContent.ts → content/getInjectedContent.ts} +3 -3
- package/src/bin/{getNav.ts → content/getNav.ts} +5 -5
- package/src/bin/content/getPlainTitle.ts +12 -0
- package/src/bin/content/getRedirectContent.ts +31 -0
- package/src/bin/content/getSectionContent.ts +80 -0
- package/src/bin/content/getStartContent.ts +40 -0
- package/src/bin/content/tweakTypography.ts +5 -0
- package/src/bin/parsing/getParsedContent.ts +28 -5
- package/src/bin/setContent.ts +16 -300
- package/src/css/base.css +2 -2
- package/src/css/index.css +1 -7
- package/biome.json +0 -35
- /package/src/bin/{toFileContent.ts → content/toFileContent.ts} +0 -0
package/src/bin/setContent.ts
CHANGED
|
@@ -1,317 +1,33 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { dirname, join } from "node:path";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { promisify } from "node:util";
|
|
6
|
-
import { packageName } from "../const/packageName.ts";
|
|
1
|
+
import { writeFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
7
3
|
import type { Context } from "../types/Context.ts";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { getNav } from "./getNav.ts";
|
|
14
|
-
import { getRepoLink } from "./getRepoLink.ts";
|
|
4
|
+
import { createDirs } from "./content/createDirs.ts";
|
|
5
|
+
import { getIndexContent } from "./content/getIndexContent.ts";
|
|
6
|
+
import { getRedirectContent } from "./content/getRedirectContent.ts";
|
|
7
|
+
import { getSectionContent } from "./content/getSectionContent.ts";
|
|
8
|
+
import { getStartContent } from "./content/getStartContent.ts";
|
|
15
9
|
import { getParsedContent } from "./parsing/getParsedContent.ts";
|
|
16
|
-
import { stripHTML } from "./stripHTML.ts";
|
|
17
|
-
import { toFileContent } from "./toFileContent.ts";
|
|
18
|
-
|
|
19
|
-
const exec = promisify(defaultExec);
|
|
20
|
-
|
|
21
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
22
|
-
const __dirname = dirname(__filename);
|
|
23
|
-
|
|
24
|
-
function getDefaultCodeStyleContent(cssRoot: string) {
|
|
25
|
-
return `
|
|
26
|
-
<link rel="stylesheet" href="https://unpkg.com/@highlightjs/cdn-assets@11.11.1/styles/stackoverflow-light.min.css" media="(prefers-color-scheme: light)">
|
|
27
|
-
<link rel="stylesheet" href="https://unpkg.com/@highlightjs/cdn-assets@11.11.1/styles/base16/material.min.css" media="(prefers-color-scheme: dark)">
|
|
28
|
-
<link rel="stylesheet" href="${cssRoot}/code.css">
|
|
29
|
-
<script src="https://unpkg.com/@highlightjs/cdn-assets@11.11.1/highlight.min.js"></script>
|
|
30
|
-
<script>hljs.highlightAll()</script>
|
|
31
|
-
`.trim();
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function tweakTypography(s = "") {
|
|
35
|
-
return s
|
|
36
|
-
.replace(/\b(for|in|on|at|to|with|a|an|the|its)\s+/gi, "$1\xa0")
|
|
37
|
-
.replace(/\b(React)\s+(apps?)\b/gi, "$1\xa0$2");
|
|
38
|
-
}
|
|
39
10
|
|
|
40
11
|
export async function setContent(ctx: Context) {
|
|
41
|
-
let {
|
|
42
|
-
dir = "",
|
|
43
|
-
assetsDir,
|
|
44
|
-
root,
|
|
45
|
-
contentDir = "",
|
|
46
|
-
name,
|
|
47
|
-
title,
|
|
48
|
-
htmlTitle,
|
|
49
|
-
description: packageDescription,
|
|
50
|
-
isDevDep,
|
|
51
|
-
backstory,
|
|
52
|
-
redirect,
|
|
53
|
-
} = ctx;
|
|
54
|
-
|
|
55
|
-
let counterContent = getCounterContent(ctx);
|
|
56
|
-
let escapedPackageDescription = escapeHTML(packageDescription);
|
|
57
|
-
|
|
58
|
-
let cssRoot = {
|
|
59
|
-
index: "",
|
|
60
|
-
content: "",
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
if (assetsDir) {
|
|
64
|
-
cssRoot.index = assetsDir;
|
|
65
|
-
cssRoot.content = `../${assetsDir}`;
|
|
66
|
-
|
|
67
|
-
await cp(join(__dirname, "css"), join(dir, cssRoot.index), {
|
|
68
|
-
force: true,
|
|
69
|
-
recursive: true,
|
|
70
|
-
});
|
|
71
|
-
} else {
|
|
72
|
-
let packageVersion = (await exec(`npm view ${packageName} version`)).stdout
|
|
73
|
-
.trim()
|
|
74
|
-
.split(".")
|
|
75
|
-
.slice(0, 2)
|
|
76
|
-
.join(".");
|
|
77
|
-
|
|
78
|
-
let packageUrl = `https://unpkg.com/${packageName}@${packageVersion}`;
|
|
79
|
-
|
|
80
|
-
cssRoot.index = `${packageUrl}/dist/css`;
|
|
81
|
-
cssRoot.content = `${packageUrl}/dist/css`;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
let icon = getIcon(ctx);
|
|
85
|
-
let iconTag = icon.url
|
|
86
|
-
? `<link rel="icon"${icon.type ? ` type="${icon.type}"` : ""} href="${icon.url}">`
|
|
87
|
-
: "";
|
|
12
|
+
let { dir = "", contentDir = "", redirect } = ctx;
|
|
88
13
|
|
|
89
14
|
if (redirect) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
await writeFile(
|
|
93
|
-
join(dir, "index.html"),
|
|
94
|
-
toFileContent(`
|
|
95
|
-
<!DOCTYPE html>
|
|
96
|
-
<html lang="en" data-layout="redirect" class="blank">
|
|
97
|
-
<head>
|
|
98
|
-
${getInjectedContent(ctx, "redirect", "head", "prepend")}
|
|
99
|
-
<meta charset="utf-8">
|
|
100
|
-
<meta name="viewport" content="width=device-width">
|
|
101
|
-
<meta http-equiv="refresh" content="0; URL=${escapedRedirect}">
|
|
102
|
-
${iconTag}
|
|
103
|
-
${getInjectedContent(ctx, "redirect", "head", "append")}
|
|
104
|
-
</head>
|
|
105
|
-
<body>
|
|
106
|
-
${getInjectedContent(ctx, "redirect", "body", "prepend")}
|
|
107
|
-
${counterContent}
|
|
108
|
-
${getInjectedContent(ctx, "redirect", "body", "append")}
|
|
109
|
-
<script>window.location.replace("${escapedRedirect}");</script>
|
|
110
|
-
</body>
|
|
111
|
-
</html>
|
|
112
|
-
`),
|
|
113
|
-
);
|
|
114
|
-
|
|
15
|
+
await writeFile(join(dir, "index.html"), getRedirectContent(ctx));
|
|
115
16
|
return;
|
|
116
17
|
}
|
|
117
18
|
|
|
118
|
-
let {
|
|
119
|
-
title: parsedTitle,
|
|
120
|
-
description,
|
|
121
|
-
intro,
|
|
122
|
-
features,
|
|
123
|
-
note,
|
|
124
|
-
installation,
|
|
125
|
-
sections,
|
|
126
|
-
nav,
|
|
127
|
-
} = await getParsedContent(ctx);
|
|
128
|
-
|
|
129
|
-
let plainTitle = escapeHTML(
|
|
130
|
-
title || stripHTML(htmlTitle || parsedTitle, true) || name,
|
|
131
|
-
);
|
|
132
|
-
let coverTitle = htmlTitle || parsedTitle || plainTitle;
|
|
133
|
-
|
|
134
|
-
let descriptionContent =
|
|
135
|
-
tweakTypography(description) ||
|
|
136
|
-
(escapedPackageDescription
|
|
137
|
-
? `<p>${tweakTypography(escapedPackageDescription)}<p>`
|
|
138
|
-
: "");
|
|
139
|
-
|
|
140
|
-
if (!installation || isDevDep !== undefined)
|
|
141
|
-
installation = `npm i${isDevDep ? " -D" : ""} ${name}`;
|
|
19
|
+
let { sections, nav } = await getParsedContent(ctx);
|
|
142
20
|
|
|
143
|
-
|
|
144
|
-
let dirs = [contentDir];
|
|
145
|
-
|
|
146
|
-
await Promise.all(
|
|
147
|
-
dirs.map(async (path) => {
|
|
148
|
-
let dirPath = join(dir, path);
|
|
149
|
-
|
|
150
|
-
try {
|
|
151
|
-
await access(dirPath);
|
|
152
|
-
} catch {
|
|
153
|
-
await mkdir(dirPath);
|
|
154
|
-
}
|
|
155
|
-
}),
|
|
156
|
-
);
|
|
21
|
+
await createDirs(ctx);
|
|
157
22
|
|
|
158
23
|
await Promise.all([
|
|
159
|
-
...sections.map(async (
|
|
24
|
+
...sections.map(async (_, i) =>
|
|
160
25
|
writeFile(
|
|
161
|
-
join(dir, contentDir, `${nav[i]?.id ?? `
|
|
162
|
-
|
|
163
|
-
<!DOCTYPE html>
|
|
164
|
-
<html lang="en" data-layout="section">
|
|
165
|
-
<head>
|
|
166
|
-
${getInjectedContent(ctx, "section", "head", "prepend")}
|
|
167
|
-
<meta charset="utf-8">
|
|
168
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
169
|
-
<meta name="description" content="${plainTitle}: ${escapeHTML(stripHTML(nav[i]?.title, true))}">
|
|
170
|
-
<title>${escapeHTML(stripHTML(nav[i]?.title, true))} | ${plainTitle}</title>
|
|
171
|
-
<link rel="stylesheet" href="${cssRoot.content}/base.css">
|
|
172
|
-
<link rel="stylesheet" href="${cssRoot.content}/section.css">
|
|
173
|
-
${iconTag}
|
|
174
|
-
${nav[i + 1]?.id ? `<link rel="prefetch" href="${root}${contentDir}/${nav[i + 1]?.id}">` : ""}
|
|
175
|
-
${nav[i - 1]?.id ? `<link rel="prefetch" href="${root}${contentDir}/${nav[i - 1]?.id}">` : ""}
|
|
176
|
-
${getInjectedContent(ctx, "section", "head", "append")}
|
|
177
|
-
</head>
|
|
178
|
-
<body>
|
|
179
|
-
${getInjectedContent(ctx, "section", "body", "prepend")}
|
|
180
|
-
<div class="layout">
|
|
181
|
-
<div class="${navContent ? "" : "no-nav "}body">
|
|
182
|
-
<main>
|
|
183
|
-
<h1><a href="${root}">${plainTitle}</a></h1>
|
|
184
|
-
${content}
|
|
185
|
-
|
|
186
|
-
<p class="pagenav">
|
|
187
|
-
<span class="prev">
|
|
188
|
-
<span class="icon">←</span>
|
|
189
|
-
${nav[i - 1]?.id ? `<a href="${root}${contentDir}/${nav[i - 1]?.id}">${nav[i - 1]?.title}</a>` : `<a href="${root}">Intro</a>`}
|
|
190
|
-
</span>
|
|
191
|
-
<span class="sep">|</span>
|
|
192
|
-
${nav[i + 1]?.id ? `<span class="next"><a href="${root}${contentDir}/${nav[i + 1]?.id}">${nav[i + 1]?.title}</a> <span class="icon">→</span></span>` : `<span class="repo">${getRepoLink(ctx)}</span>`}
|
|
193
|
-
</p>
|
|
194
|
-
</main>
|
|
195
|
-
${navContent ? "<hr>" : ""}
|
|
196
|
-
${navContent.replace(
|
|
197
|
-
new RegExp(
|
|
198
|
-
`(<li data-id="${escapeRegExp(nav[i]?.id)}">)<a href="[^"]+">([^<]+)</a>`,
|
|
199
|
-
),
|
|
200
|
-
"$1<strong>$2</strong>",
|
|
201
|
-
)}
|
|
202
|
-
</div>
|
|
203
|
-
</div>
|
|
204
|
-
|
|
205
|
-
${
|
|
206
|
-
content.includes("<pre><code ")
|
|
207
|
-
? getInjectedContent(ctx, "section", ":has-code", "append") ||
|
|
208
|
-
getDefaultCodeStyleContent(cssRoot.content)
|
|
209
|
-
: ""
|
|
210
|
-
}
|
|
211
|
-
${counterContent}
|
|
212
|
-
${getInjectedContent(ctx, "section", "body", "append")}
|
|
213
|
-
</body>
|
|
214
|
-
</html>
|
|
215
|
-
`),
|
|
26
|
+
join(dir, contentDir, `${nav[i]?.id ?? `_Section_${i + 1}`}.html`),
|
|
27
|
+
await getSectionContent(ctx, i),
|
|
216
28
|
),
|
|
217
29
|
),
|
|
218
|
-
writeFile(
|
|
219
|
-
|
|
220
|
-
toFileContent(`
|
|
221
|
-
<!DOCTYPE html>
|
|
222
|
-
<html lang="en" data-layout="index">
|
|
223
|
-
<head>
|
|
224
|
-
${getInjectedContent(ctx, "index", "head", "prepend")}
|
|
225
|
-
<meta charset="utf-8">
|
|
226
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
227
|
-
<meta name="description" content="${plainTitle}${escapedPackageDescription ? `: ${escapedPackageDescription}` : ""}">
|
|
228
|
-
<title>${plainTitle}${escapedPackageDescription ? ` | ${escapedPackageDescription}` : ""}</title>
|
|
229
|
-
<link rel="stylesheet" href="${cssRoot.index}/base.css">
|
|
230
|
-
<link rel="stylesheet" href="${cssRoot.index}/index.css">
|
|
231
|
-
${iconTag}
|
|
232
|
-
<link rel="prefetch" href="${root}start">
|
|
233
|
-
${nav[0] ? `<link rel="prefetch" href="${root}${contentDir}/${nav[0]?.id ?? ""}">` : ""}
|
|
234
|
-
${getInjectedContent(ctx, "index", "head", "append")}
|
|
235
|
-
</head>
|
|
236
|
-
<body>
|
|
237
|
-
${getInjectedContent(ctx, "index", "body", "prepend")}
|
|
238
|
-
<div class="layout">
|
|
239
|
-
<main>
|
|
240
|
-
<section class="aux intro-title">
|
|
241
|
-
<div class="section-content">
|
|
242
|
-
${getInjectedContent(ctx, "index", "cover", "prepend")}
|
|
243
|
-
<h1>${coverTitle}</h1>
|
|
244
|
-
<div class="description">
|
|
245
|
-
${descriptionContent}
|
|
246
|
-
</div>
|
|
247
|
-
<p class="actions">
|
|
248
|
-
<a href="${root}start" class="primary">Docs</a>
|
|
249
|
-
<span class="sep"> • </span>
|
|
250
|
-
${getRepoLink(ctx)}
|
|
251
|
-
</p>
|
|
252
|
-
${backstory ? `<p class="ref"><a href="${backstory}">Backstory</a></p>` : ""}
|
|
253
|
-
<p class="installation"><code>${escapeHTML(installation)}</code></p>
|
|
254
|
-
${getInjectedContent(ctx, "index", "cover", "append")}
|
|
255
|
-
</div>
|
|
256
|
-
</section>
|
|
257
|
-
${
|
|
258
|
-
intro || features || note
|
|
259
|
-
? `
|
|
260
|
-
<section class="intro">
|
|
261
|
-
<div class="section-content">
|
|
262
|
-
${intro ? `<div class="intro">${intro}</div>` : ""}
|
|
263
|
-
${features ? `<div class="features">${features}</div>` : ""}
|
|
264
|
-
${note ? `<div class="note">${note}</div>` : ""}
|
|
265
|
-
<p class="pagenav">
|
|
266
|
-
<span class="next"><a href="${root}start">To the docs</a> <span class="icon">→</span></span>
|
|
267
|
-
</p>
|
|
268
|
-
</div>
|
|
269
|
-
</section>
|
|
270
|
-
`
|
|
271
|
-
: ""
|
|
272
|
-
}
|
|
273
|
-
</main>
|
|
274
|
-
</div>
|
|
275
|
-
|
|
276
|
-
${
|
|
277
|
-
[description, intro, features, note].some((s) => s.includes("<pre><code "))
|
|
278
|
-
? getInjectedContent(ctx, "index", ":has-code", "append") ||
|
|
279
|
-
getDefaultCodeStyleContent(cssRoot.index)
|
|
280
|
-
: ""
|
|
281
|
-
}
|
|
282
|
-
${counterContent}
|
|
283
|
-
${getInjectedContent(ctx, "index", "body", "append")}
|
|
284
|
-
</body>
|
|
285
|
-
</html>
|
|
286
|
-
`),
|
|
287
|
-
),
|
|
288
|
-
writeFile(
|
|
289
|
-
join(dir, "start.html"),
|
|
290
|
-
toFileContent(`
|
|
291
|
-
<!DOCTYPE html>
|
|
292
|
-
<html lang="en" data-layout="start" class="blank">
|
|
293
|
-
<head>
|
|
294
|
-
${getInjectedContent(ctx, "start", "head", "prepend")}
|
|
295
|
-
<meta charset="utf-8">
|
|
296
|
-
<meta name="viewport" content="width=device-width">
|
|
297
|
-
<meta http-equiv="refresh" content="0; URL=${root}${contentDir}/${nav[0]?.id}">
|
|
298
|
-
<title>${plainTitle}</title>
|
|
299
|
-
<link rel="stylesheet" href="${cssRoot.index}/base.css">
|
|
300
|
-
${iconTag}
|
|
301
|
-
<script>window.location.replace("${root}${contentDir}/${nav[0]?.id}");</script>
|
|
302
|
-
${getInjectedContent(ctx, "start", "head", "append")}
|
|
303
|
-
</head>
|
|
304
|
-
<body>
|
|
305
|
-
${getInjectedContent(ctx, "start", "body", "prepend")}
|
|
306
|
-
<div class="layout">
|
|
307
|
-
<h1>${plainTitle}</h1>
|
|
308
|
-
</div>
|
|
309
|
-
|
|
310
|
-
${counterContent}
|
|
311
|
-
${getInjectedContent(ctx, "start", "body", "append")}
|
|
312
|
-
</body>
|
|
313
|
-
</html>
|
|
314
|
-
`),
|
|
315
|
-
),
|
|
30
|
+
writeFile(join(dir, "index.html"), await getIndexContent(ctx)),
|
|
31
|
+
writeFile(join(dir, "start.html"), await getStartContent(ctx)),
|
|
316
32
|
]);
|
|
317
33
|
}
|
package/src/css/base.css
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
--aux-color: #797979;
|
|
10
10
|
--aux-background: #f2f2f2;
|
|
11
|
-
--aux-background-end: #
|
|
11
|
+
--aux-background-end: #f2f2f2;
|
|
12
12
|
--aux-border-color: #828282;
|
|
13
13
|
--aux-link-color: royalblue;
|
|
14
14
|
--aux-secondary-color: var(--color);
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
|
|
30
30
|
--aux-color: #8e9198;
|
|
31
31
|
--aux-background: #1d2331;
|
|
32
|
-
--aux-background-end: #
|
|
32
|
+
--aux-background-end: #1d2331;
|
|
33
33
|
--aux-border-color: #49587b;
|
|
34
34
|
--aux-link-color: deepskyblue;
|
|
35
35
|
--aux-secondary-color: var(--color);
|
package/src/css/index.css
CHANGED
|
@@ -106,7 +106,7 @@ section {
|
|
|
106
106
|
}
|
|
107
107
|
section .section-content {
|
|
108
108
|
max-width: var(--max-content-width);
|
|
109
|
-
padding:
|
|
109
|
+
padding: 15vh 2.5em;
|
|
110
110
|
box-sizing: border-box;
|
|
111
111
|
}
|
|
112
112
|
section.intro-title {
|
|
@@ -127,10 +127,8 @@ section.intro-title {
|
|
|
127
127
|
section.intro-title .section-content {
|
|
128
128
|
display: flex;
|
|
129
129
|
flex-direction: column;
|
|
130
|
-
justify-content: center;
|
|
131
130
|
align-items: flex-end;
|
|
132
131
|
max-width: 24em;
|
|
133
|
-
min-height: 95vh;
|
|
134
132
|
}
|
|
135
133
|
section.intro-title:last-of-type {
|
|
136
134
|
width: 100%;
|
|
@@ -147,7 +145,6 @@ section.intro {
|
|
|
147
145
|
display: flex;
|
|
148
146
|
width: 60%;
|
|
149
147
|
flex-direction: column;
|
|
150
|
-
justify-content: center;
|
|
151
148
|
}
|
|
152
149
|
section.intro .section-content {
|
|
153
150
|
width: 100%;
|
|
@@ -244,9 +241,6 @@ section.intro pre {
|
|
|
244
241
|
padding: 0;
|
|
245
242
|
}
|
|
246
243
|
}
|
|
247
|
-
.pagenav {
|
|
248
|
-
text-align: right;
|
|
249
|
-
}
|
|
250
244
|
p.installation {
|
|
251
245
|
margin: 0;
|
|
252
246
|
}
|
package/biome.json
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"formatter": {
|
|
3
|
-
"indentStyle": "space"
|
|
4
|
-
},
|
|
5
|
-
"linter": {
|
|
6
|
-
"rules": {
|
|
7
|
-
"a11y": {
|
|
8
|
-
"noAutofocus": "off",
|
|
9
|
-
"useButtonType": "off",
|
|
10
|
-
"useHtmlLang": "off"
|
|
11
|
-
},
|
|
12
|
-
"security": {
|
|
13
|
-
"noDangerouslySetInnerHtml": "off"
|
|
14
|
-
},
|
|
15
|
-
"style": {
|
|
16
|
-
"noDescendingSpecificity": "off",
|
|
17
|
-
"noNonNullAssertion": "off",
|
|
18
|
-
"useConst": "off"
|
|
19
|
-
},
|
|
20
|
-
"suspicious": {
|
|
21
|
-
"noArrayIndexKey": "off",
|
|
22
|
-
"noAssignInExpressions": "off",
|
|
23
|
-
"noConfusingVoidType": "off"
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
"vcs": {
|
|
28
|
-
"enabled": true,
|
|
29
|
-
"clientKind": "git",
|
|
30
|
-
"useIgnoreFile": true
|
|
31
|
-
},
|
|
32
|
-
"files": {
|
|
33
|
-
"includes": ["**", "!schema.json"]
|
|
34
|
-
}
|
|
35
|
-
}
|
|
File without changes
|