@unciatech/file-manager 0.0.6 → 0.0.8
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.md +28 -39
- package/dist/cli.js +37 -18
- package/dist/cli.mjs +36 -17
- package/dist/index.js +10 -10
- package/dist/index.mjs +21 -21
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,29 +47,15 @@ npx @unciatech/file-manager init my-media-app
|
|
|
47
47
|
```
|
|
48
48
|
*It will ask if you want Next.js or Vite (React), install Tailwind, install the package, and set everything up for you!*
|
|
49
49
|
|
|
50
|
-
**(CRITICAL)
|
|
51
|
-
|
|
50
|
+
**(CRITICAL) Import the stylesheet:**
|
|
51
|
+
This library ships pre-built CSS. You simply need to import it **once** in your root layout:
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
import
|
|
56
|
-
|
|
57
|
-
const config: Config = {
|
|
58
|
-
content: [
|
|
59
|
-
// Your existing paths...
|
|
60
|
-
"./node_modules/@unciatech/file-manager/dist/**/*.js",
|
|
61
|
-
"./node_modules/@unciatech/file-manager/dist/**/*.mjs",
|
|
62
|
-
],
|
|
63
|
-
// ...
|
|
64
|
-
};
|
|
65
|
-
export default config;
|
|
53
|
+
```tsx
|
|
54
|
+
// app/layout.tsx (Next.js) or src/main.tsx (Vite)
|
|
55
|
+
import '@unciatech/file-manager/styles';
|
|
66
56
|
```
|
|
67
57
|
|
|
68
|
-
|
|
69
|
-
```css
|
|
70
|
-
@import "tailwindcss";
|
|
71
|
-
@source "../node_modules/@unciatech/file-manager/dist";
|
|
72
|
-
```
|
|
58
|
+
That's it — no Tailwind config changes needed.
|
|
73
59
|
|
|
74
60
|
### Step 2: Create your Custom API Provider
|
|
75
61
|
|
|
@@ -129,40 +115,43 @@ export class MyCustomApiProvider implements IFileManagerProvider {
|
|
|
129
115
|
> **💡 Pro Tip - The Mock Provider:**
|
|
130
116
|
> If you are just prototyping and don't have a backend ready yet, you can skip Step 2 entirely! We included a fully functional `MockFileManagerProvider` that fakes network latency and stores data in memory. Just import it and use it right away to see the UI in action.
|
|
131
117
|
|
|
132
|
-
### Step 3:
|
|
118
|
+
### Step 3: Set Up the Route & Render
|
|
133
119
|
|
|
134
|
-
|
|
120
|
+
Because the file manager navigates into subfolders via URL (e.g. `/media/3/45`), you need a **catch-all route** in your Next.js app:
|
|
135
121
|
|
|
136
122
|
```tsx
|
|
137
|
-
// app/media/page.tsx
|
|
138
|
-
|
|
139
|
-
import { FileManager } from "@/components/file-manager";
|
|
123
|
+
// app/media/[[...path]]/page.tsx
|
|
124
|
+
"use client";
|
|
140
125
|
|
|
141
|
-
|
|
142
|
-
import {
|
|
143
|
-
|
|
126
|
+
import { Suspense } from "react";
|
|
127
|
+
import { FileManager } from "@unciatech/file-manager";
|
|
128
|
+
import { MyCustomApiProvider } from "@/lib/my-api-provider";
|
|
144
129
|
|
|
145
|
-
|
|
146
|
-
// Instantiate the provider
|
|
147
|
-
const apiProvider = new MyCustomApiProvider();
|
|
130
|
+
const provider = new MyCustomApiProvider();
|
|
148
131
|
|
|
132
|
+
export default function MediaPage() {
|
|
149
133
|
return (
|
|
150
134
|
<div className="h-screen w-full">
|
|
151
|
-
<
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
</
|
|
135
|
+
<Suspense fallback={<div className="p-4">Loading...</div>}>
|
|
136
|
+
<FileManager
|
|
137
|
+
allowedFileTypes={["audios", "videos", "images", "files"]}
|
|
138
|
+
viewMode="grid"
|
|
139
|
+
basePath="media"
|
|
140
|
+
provider={provider}
|
|
141
|
+
/>
|
|
142
|
+
</Suspense>
|
|
159
143
|
</div>
|
|
160
144
|
);
|
|
161
145
|
}
|
|
162
146
|
```
|
|
163
147
|
|
|
148
|
+
> **`basePath` prop** — Set this to the URL segment where your file manager lives (e.g. `"media"` if mounted at `/media/[[...path]]`). This is required for folder navigation to work correctly — without it, clicking into a folder will 404.
|
|
149
|
+
|
|
150
|
+
> **💡 Quick start with mock data:** Use `import { MockProvider } from '@unciatech/file-manager'` to skip Step 2 and prototype immediately.
|
|
151
|
+
|
|
164
152
|
---
|
|
165
153
|
|
|
154
|
+
|
|
166
155
|
## 💾 Database Schema Design
|
|
167
156
|
|
|
168
157
|
Because this application relies heavily on tree structures (Folders inside Folders) and varied JSON metadata (Video durations vs Document page counts), using a relational database with JSONB support (like PostgreSQL) is highly recommended.
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";var
|
|
2
|
+
"use strict";var v=Object.create;var u=Object.defineProperty;var x=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var F=Object.getPrototypeOf,M=Object.prototype.hasOwnProperty;var j=(n,e,s,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let c of S(e))!M.call(n,c)&&c!==s&&u(n,c,{get:()=>e[c],enumerable:!(t=x(e,c))||t.enumerable});return n};var d=(n,e,s)=>(s=n!=null?v(F(n)):{},j(e||!n||!n.__esModule?u(s,"default",{value:n,enumerable:!0}):s,n));var i=d(require("fs")),o=d(require("path")),l=require("child_process"),f=d(require("readline")),y=process.argv.slice(2),P=y[0],p=y[1],k=f.default.createInterface({input:process.stdin,output:process.stdout}),C=n=>new Promise(e=>k.question(n,e)),g=`"use client";
|
|
3
3
|
|
|
4
4
|
import React, { Suspense } from "react";
|
|
5
5
|
import { FileManager, MockProvider } from "@unciatech/file-manager";
|
|
@@ -13,19 +13,41 @@ export default function FileManagerDemo() {
|
|
|
13
13
|
<FileManager
|
|
14
14
|
allowedFileTypes={["audios", "videos", "images", "files"]}
|
|
15
15
|
viewMode="grid"
|
|
16
|
+
basePath="media"
|
|
16
17
|
provider={mockProvider}
|
|
17
18
|
/>
|
|
18
19
|
</Suspense>
|
|
19
20
|
</div>
|
|
20
21
|
);
|
|
21
22
|
}
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
`,N=`"use client";
|
|
24
|
+
|
|
25
|
+
import { Suspense } from "react";
|
|
26
|
+
import { FileManager, MockProvider } from "@unciatech/file-manager";
|
|
27
|
+
|
|
28
|
+
const mockProvider = new MockProvider();
|
|
29
|
+
|
|
30
|
+
export default function MediaPage() {
|
|
31
|
+
return (
|
|
32
|
+
<div className="h-screen w-full">
|
|
33
|
+
<Suspense fallback={<div className="p-4">Loading...</div>}>
|
|
34
|
+
<FileManager
|
|
35
|
+
allowedFileTypes={["audios", "videos", "images", "files"]}
|
|
36
|
+
viewMode="grid"
|
|
37
|
+
basePath="media"
|
|
38
|
+
provider={mockProvider}
|
|
39
|
+
/>
|
|
40
|
+
</Suspense>
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
`;async function T(){if(P!=="init"&&(console.log("Usage: npx @unciatech/file-manager init [project-name]"),process.exit(0)),!p){console.log("\u{1F680} Generating <FileManagerDemo /> component in the current project...");let s=process.cwd();i.default.existsSync(o.default.join(process.cwd(),"components"))?s=o.default.join(process.cwd(),"components"):i.default.existsSync(o.default.join(process.cwd(),"src","components"))&&(s=o.default.join(process.cwd(),"src","components"));let t=o.default.join(s,"FileManagerDemo.tsx");i.default.existsSync(t)&&(console.error(`\u274C Error: ${t} already exists.`),process.exit(1)),i.default.writeFileSync(t,g,"utf-8"),console.log(`\u2705 Success! Created ${t}`),console.log(""),console.log("You can now import and render <FileManagerDemo /> anywhere in your application."),console.log(""),console.log("\u26A0\uFE0F IMPORTANT: Add the styles import to your layout.tsx or _app.tsx:"),console.log(" import '@unciatech/file-manager/styles';"),console.log(""),console.log("\u26A0\uFE0F IMPORTANT: Create the catch-all route for folder navigation:"),console.log(" app/media/[[...path]]/page.tsx (Next.js)"),console.log(" See the README for the full page template."),process.exit(0)}console.log(`
|
|
45
|
+
\u{1F680} Initializing a new application: ${p}
|
|
24
46
|
`),console.log("Which framework would you like to use?"),console.log(" 1) Next.js (App Router, Tailwind v4)"),console.log(" 2) Vite (React, Tailwind v4)"),console.log(" 3) Cancel");let n=await C(`
|
|
25
|
-
Select an option (1-3): `),e=
|
|
26
|
-
\u274C Scaffolding failed:`,
|
|
27
|
-
\u{1F4E6} Creating Next.js application (this may take a minute)...`),(0,
|
|
28
|
-
\u{1F4E6} Installing dependencies (@unciatech/file-manager, tailwindcss-animate)...`),(0,
|
|
47
|
+
Select an option (1-3): `),e=o.default.join(process.cwd(),p);try{n==="1"?await A(p,e):n==="2"?await b(p,e):(console.log("Canceled."),process.exit(0))}catch(s){console.error(`
|
|
48
|
+
\u274C Scaffolding failed:`,s),process.exit(1)}process.exit(0)}async function A(n,e){console.log(`
|
|
49
|
+
\u{1F4E6} Creating Next.js application (this may take a minute)...`),(0,l.execSync)(`npx create-next-app@latest ${n} --ts --tailwind --eslint --app --src-dir --import-alias "@/*" --use-npm`,{stdio:"inherit"}),console.log(`
|
|
50
|
+
\u{1F4E6} Installing dependencies (@unciatech/file-manager, tailwindcss-animate)...`),(0,l.execSync)("npm install @unciatech/file-manager tailwindcss-animate",{cwd:e,stdio:"inherit"});let s=o.default.join(e,"src","components");i.default.existsSync(s)||i.default.mkdirSync(s,{recursive:!0}),i.default.writeFileSync(o.default.join(s,"FileManagerDemo.tsx"),g,"utf-8");let t=o.default.join(e,"src","app","media","[[...path]]");i.default.mkdirSync(t,{recursive:!0}),i.default.writeFileSync(o.default.join(t,"page.tsx"),N,"utf-8");let c=o.default.join(e,"src","app","page.tsx");i.default.writeFileSync(c,`import FileManagerDemo from "@/components/FileManagerDemo";
|
|
29
51
|
|
|
30
52
|
export default function Home() {
|
|
31
53
|
return (
|
|
@@ -34,13 +56,10 @@ export default function Home() {
|
|
|
34
56
|
</main>
|
|
35
57
|
);
|
|
36
58
|
}
|
|
37
|
-
`);let
|
|
38
|
-
|
|
39
|
-
@
|
|
40
|
-
|
|
41
|
-
`+r.replace('@import "tailwindcss";',""),i.default.writeFileSync(t,r))}f(n)}async function b(n,e){console.log(`
|
|
42
|
-
\u{1F4E6} Creating Vite React application...`),(0,a.execSync)(`npm create vite@latest ${n} -- --template react-ts`,{stdio:"inherit"}),console.log(`
|
|
43
|
-
\u{1F4E6} Installing dependencies (Tailwind + File Manager)...`),(0,a.execSync)("npm install",{cwd:e,stdio:"inherit"}),(0,a.execSync)("npm install tailwindcss @tailwindcss/vite @unciatech/file-manager",{cwd:e,stdio:"inherit"});let o=s.default.join(e,"vite.config.ts");i.default.writeFileSync(o,`import { defineConfig } from 'vite'
|
|
59
|
+
`);let r=o.default.join(e,"src","app","layout.tsx");if(i.default.existsSync(r)){let a=i.default.readFileSync(r,"utf8");a.includes("@unciatech/file-manager/styles")||(a=`import '@unciatech/file-manager/styles';
|
|
60
|
+
`+a,i.default.writeFileSync(r,a))}w(n)}async function b(n,e){console.log(`
|
|
61
|
+
\u{1F4E6} Creating Vite React application...`),(0,l.execSync)(`npm create vite@latest ${n} -- --template react-ts`,{stdio:"inherit"}),console.log(`
|
|
62
|
+
\u{1F4E6} Installing dependencies (Tailwind + File Manager)...`),(0,l.execSync)("npm install",{cwd:e,stdio:"inherit"}),(0,l.execSync)("npm install tailwindcss @tailwindcss/vite @unciatech/file-manager",{cwd:e,stdio:"inherit"});let s=o.default.join(e,"vite.config.ts");i.default.writeFileSync(s,`import { defineConfig } from 'vite'
|
|
44
63
|
import react from '@vitejs/plugin-react'
|
|
45
64
|
import tailwindcss from '@tailwindcss/vite'
|
|
46
65
|
|
|
@@ -50,9 +69,9 @@ export default defineConfig({
|
|
|
50
69
|
tailwindcss(),
|
|
51
70
|
],
|
|
52
71
|
})
|
|
53
|
-
`);let
|
|
54
|
-
|
|
55
|
-
|
|
72
|
+
`);let c=o.default.join(e,"src","index.css");i.default.writeFileSync(c,`@import "tailwindcss";
|
|
73
|
+
`);let r=o.default.join(e,"src","main.tsx");if(i.default.existsSync(r)){let m=i.default.readFileSync(r,"utf8");m.includes("@unciatech/file-manager/styles")||(m=`import '@unciatech/file-manager/styles';
|
|
74
|
+
`+m,i.default.writeFileSync(r,m))}let a=o.default.join(e,"src","components");i.default.existsSync(a)||i.default.mkdirSync(a,{recursive:!0}),i.default.writeFileSync(o.default.join(a,"FileManagerDemo.tsx"),g,"utf-8");let h=o.default.join(e,"src","App.tsx");i.default.writeFileSync(h,`import FileManagerDemo from "./components/FileManagerDemo";
|
|
56
75
|
|
|
57
76
|
function App() {
|
|
58
77
|
return (
|
|
@@ -63,4 +82,4 @@ function App() {
|
|
|
63
82
|
}
|
|
64
83
|
|
|
65
84
|
export default App;
|
|
66
|
-
`),
|
|
85
|
+
`),w(n,"npm run dev")}function w(n,e="npm run dev"){console.log("\\n========================================="),console.log("\u{1F389} Your Media Library application is ready!"),console.log("========================================="),console.log("\\nNext steps:"),console.log(` cd ${n}`),console.log(` ${e}`),console.log("\\nEnjoy building! \u{1F5C2}\uFE0F\\n")}T();
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
2
|
+
import e from"fs";import i from"path";import{execSync as l}from"child_process";import y from"readline";var g=process.argv.slice(2),w=g[0],r=g[1],h=y.createInterface({input:process.stdin,output:process.stdout}),v=o=>new Promise(n=>h.question(o,n)),d=`"use client";
|
|
3
3
|
|
|
4
4
|
import React, { Suspense } from "react";
|
|
5
5
|
import { FileManager, MockProvider } from "@unciatech/file-manager";
|
|
@@ -13,19 +13,41 @@ export default function FileManagerDemo() {
|
|
|
13
13
|
<FileManager
|
|
14
14
|
allowedFileTypes={["audios", "videos", "images", "files"]}
|
|
15
15
|
viewMode="grid"
|
|
16
|
+
basePath="media"
|
|
16
17
|
provider={mockProvider}
|
|
17
18
|
/>
|
|
18
19
|
</Suspense>
|
|
19
20
|
</div>
|
|
20
21
|
);
|
|
21
22
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
`,x=`"use client";
|
|
24
|
+
|
|
25
|
+
import { Suspense } from "react";
|
|
26
|
+
import { FileManager, MockProvider } from "@unciatech/file-manager";
|
|
27
|
+
|
|
28
|
+
const mockProvider = new MockProvider();
|
|
29
|
+
|
|
30
|
+
export default function MediaPage() {
|
|
31
|
+
return (
|
|
32
|
+
<div className="h-screen w-full">
|
|
33
|
+
<Suspense fallback={<div className="p-4">Loading...</div>}>
|
|
34
|
+
<FileManager
|
|
35
|
+
allowedFileTypes={["audios", "videos", "images", "files"]}
|
|
36
|
+
viewMode="grid"
|
|
37
|
+
basePath="media"
|
|
38
|
+
provider={mockProvider}
|
|
39
|
+
/>
|
|
40
|
+
</Suspense>
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
`;async function S(){if(w!=="init"&&(console.log("Usage: npx @unciatech/file-manager init [project-name]"),process.exit(0)),!r){console.log("\u{1F680} Generating <FileManagerDemo /> component in the current project...");let s=process.cwd();e.existsSync(i.join(process.cwd(),"components"))?s=i.join(process.cwd(),"components"):e.existsSync(i.join(process.cwd(),"src","components"))&&(s=i.join(process.cwd(),"src","components"));let t=i.join(s,"FileManagerDemo.tsx");e.existsSync(t)&&(console.error(`\u274C Error: ${t} already exists.`),process.exit(1)),e.writeFileSync(t,d,"utf-8"),console.log(`\u2705 Success! Created ${t}`),console.log(""),console.log("You can now import and render <FileManagerDemo /> anywhere in your application."),console.log(""),console.log("\u26A0\uFE0F IMPORTANT: Add the styles import to your layout.tsx or _app.tsx:"),console.log(" import '@unciatech/file-manager/styles';"),console.log(""),console.log("\u26A0\uFE0F IMPORTANT: Create the catch-all route for folder navigation:"),console.log(" app/media/[[...path]]/page.tsx (Next.js)"),console.log(" See the README for the full page template."),process.exit(0)}console.log(`
|
|
45
|
+
\u{1F680} Initializing a new application: ${r}
|
|
46
|
+
`),console.log("Which framework would you like to use?"),console.log(" 1) Next.js (App Router, Tailwind v4)"),console.log(" 2) Vite (React, Tailwind v4)"),console.log(" 3) Cancel");let o=await v(`
|
|
47
|
+
Select an option (1-3): `),n=i.join(process.cwd(),r);try{o==="1"?await F(r,n):o==="2"?await M(r,n):(console.log("Canceled."),process.exit(0))}catch(s){console.error(`
|
|
48
|
+
\u274C Scaffolding failed:`,s),process.exit(1)}process.exit(0)}async function F(o,n){console.log(`
|
|
27
49
|
\u{1F4E6} Creating Next.js application (this may take a minute)...`),l(`npx create-next-app@latest ${o} --ts --tailwind --eslint --app --src-dir --import-alias "@/*" --use-npm`,{stdio:"inherit"}),console.log(`
|
|
28
|
-
\u{1F4E6} Installing dependencies (@unciatech/file-manager, tailwindcss-animate)...`),l("npm install @unciatech/file-manager tailwindcss-animate",{cwd:
|
|
50
|
+
\u{1F4E6} Installing dependencies (@unciatech/file-manager, tailwindcss-animate)...`),l("npm install @unciatech/file-manager tailwindcss-animate",{cwd:n,stdio:"inherit"});let s=i.join(n,"src","components");e.existsSync(s)||e.mkdirSync(s,{recursive:!0}),e.writeFileSync(i.join(s,"FileManagerDemo.tsx"),d,"utf-8");let t=i.join(n,"src","app","media","[[...path]]");e.mkdirSync(t,{recursive:!0}),e.writeFileSync(i.join(t,"page.tsx"),x,"utf-8");let m=i.join(n,"src","app","page.tsx");e.writeFileSync(m,`import FileManagerDemo from "@/components/FileManagerDemo";
|
|
29
51
|
|
|
30
52
|
export default function Home() {
|
|
31
53
|
return (
|
|
@@ -34,13 +56,10 @@ export default function Home() {
|
|
|
34
56
|
</main>
|
|
35
57
|
);
|
|
36
58
|
}
|
|
37
|
-
`);let
|
|
38
|
-
|
|
39
|
-
@source "../../node_modules/@unciatech/file-manager/dist";
|
|
40
|
-
|
|
41
|
-
`+t.replace('@import "tailwindcss";',""),n.writeFileSync(r,t))}d(o)}async function h(o,e){console.log(`
|
|
59
|
+
`);let a=i.join(n,"src","app","layout.tsx");if(e.existsSync(a)){let c=e.readFileSync(a,"utf8");c.includes("@unciatech/file-manager/styles")||(c=`import '@unciatech/file-manager/styles';
|
|
60
|
+
`+c,e.writeFileSync(a,c))}u(o)}async function M(o,n){console.log(`
|
|
42
61
|
\u{1F4E6} Creating Vite React application...`),l(`npm create vite@latest ${o} -- --template react-ts`,{stdio:"inherit"}),console.log(`
|
|
43
|
-
\u{1F4E6} Installing dependencies (Tailwind + File Manager)...`),l("npm install",{cwd:
|
|
62
|
+
\u{1F4E6} Installing dependencies (Tailwind + File Manager)...`),l("npm install",{cwd:n,stdio:"inherit"}),l("npm install tailwindcss @tailwindcss/vite @unciatech/file-manager",{cwd:n,stdio:"inherit"});let s=i.join(n,"vite.config.ts");e.writeFileSync(s,`import { defineConfig } from 'vite'
|
|
44
63
|
import react from '@vitejs/plugin-react'
|
|
45
64
|
import tailwindcss from '@tailwindcss/vite'
|
|
46
65
|
|
|
@@ -50,9 +69,9 @@ export default defineConfig({
|
|
|
50
69
|
tailwindcss(),
|
|
51
70
|
],
|
|
52
71
|
})
|
|
53
|
-
`);let
|
|
54
|
-
|
|
55
|
-
|
|
72
|
+
`);let m=i.join(n,"src","index.css");e.writeFileSync(m,`@import "tailwindcss";
|
|
73
|
+
`);let a=i.join(n,"src","main.tsx");if(e.existsSync(a)){let p=e.readFileSync(a,"utf8");p.includes("@unciatech/file-manager/styles")||(p=`import '@unciatech/file-manager/styles';
|
|
74
|
+
`+p,e.writeFileSync(a,p))}let c=i.join(n,"src","components");e.existsSync(c)||e.mkdirSync(c,{recursive:!0}),e.writeFileSync(i.join(c,"FileManagerDemo.tsx"),d,"utf-8");let f=i.join(n,"src","App.tsx");e.writeFileSync(f,`import FileManagerDemo from "./components/FileManagerDemo";
|
|
56
75
|
|
|
57
76
|
function App() {
|
|
58
77
|
return (
|
|
@@ -63,4 +82,4 @@ function App() {
|
|
|
63
82
|
}
|
|
64
83
|
|
|
65
84
|
export default App;
|
|
66
|
-
`),
|
|
85
|
+
`),u(o,"npm run dev")}function u(o,n="npm run dev"){console.log("\\n========================================="),console.log("\u{1F389} Your Media Library application is ready!"),console.log("========================================="),console.log("\\nNext steps:"),console.log(` cd ${o}`),console.log(` ${n}`),console.log("\\nEnjoy building! \u{1F5C2}\uFE0F\\n")}S();
|