@remotion/bundler 3.0.19 → 3.0.22
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/bundle.js +3 -2
- package/dist/error-overlay/remotion-overlay/carets.d.ts +1 -0
- package/dist/homepage/homepage.d.ts +0 -1
- package/dist/homepage/homepage.js +2 -3
- package/dist/index.d.ts +17 -16
- package/dist/index.js +8 -9
- package/dist/renderEntry.js +28 -21
- package/dist/webpack-config.d.ts +2 -1
- package/dist/webpack-config.js +6 -14
- package/package.json +3 -15
- package/web/favicon.png +0 -0
package/dist/bundle.js
CHANGED
|
@@ -11,7 +11,7 @@ const remotion_1 = require("remotion");
|
|
|
11
11
|
const util_1 = require("util");
|
|
12
12
|
const webpack_1 = __importDefault(require("webpack"));
|
|
13
13
|
const copy_dir_1 = require("./copy-dir");
|
|
14
|
-
const
|
|
14
|
+
const index_html_1 = require("./index-html");
|
|
15
15
|
const webpack_config_1 = require("./webpack-config");
|
|
16
16
|
const entry = require.resolve('./renderEntry');
|
|
17
17
|
const promisified = (0, util_1.promisify)(webpack_1.default);
|
|
@@ -50,6 +50,7 @@ const bundle = async (entryPoint, onProgressUpdate, options) => {
|
|
|
50
50
|
// For production, the variables are set dynamically
|
|
51
51
|
envVariables: {},
|
|
52
52
|
inputProps: {},
|
|
53
|
+
entryPoints: [],
|
|
53
54
|
}),
|
|
54
55
|
]);
|
|
55
56
|
if (!output) {
|
|
@@ -69,7 +70,7 @@ const bundle = async (entryPoint, onProgressUpdate, options) => {
|
|
|
69
70
|
if (fs_1.default.existsSync(from)) {
|
|
70
71
|
await (0, copy_dir_1.copyDir)(from, to);
|
|
71
72
|
}
|
|
72
|
-
const html = (0,
|
|
73
|
+
const html = (0, index_html_1.indexHtml)(publicDir, baseDir, null);
|
|
73
74
|
fs_1.default.writeFileSync(path_1.default.join(outDir, 'index.html'), html);
|
|
74
75
|
return outDir;
|
|
75
76
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Homepage =
|
|
3
|
+
exports.Homepage = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const react_1 = require("react");
|
|
6
6
|
const bundle_mode_1 = require("../bundle-mode");
|
|
@@ -55,9 +55,8 @@ const AvailableCompositions = () => {
|
|
|
55
55
|
return (0, jsx_runtime_1.jsx)("li", { children: c.id }, c.id);
|
|
56
56
|
}) })] }));
|
|
57
57
|
};
|
|
58
|
-
exports.AvailableCompositions = AvailableCompositions;
|
|
59
58
|
const Homepage = () => {
|
|
60
59
|
const url = window.location.origin + window.location.pathname;
|
|
61
|
-
return ((0, jsx_runtime_1.jsxs)("div", { style: container, children: [(0, jsx_runtime_1.jsx)("h1", { children: "Remotion Bundle" }), "This is a website which contains a bundled Remotion video. You can render videos based on this URL.", (0, jsx_runtime_1.jsx)("h2", { children: "Available compositions" }), (0, jsx_runtime_1.jsx)(
|
|
60
|
+
return ((0, jsx_runtime_1.jsxs)("div", { style: container, children: [(0, jsx_runtime_1.jsx)("h1", { children: "Remotion Bundle" }), "This is a website which contains a bundled Remotion video. You can render videos based on this URL.", (0, jsx_runtime_1.jsx)("h2", { children: "Available compositions" }), (0, jsx_runtime_1.jsx)(AvailableCompositions, {}), (0, jsx_runtime_1.jsx)("h2", { children: "How to render" }), "Locally: ", (0, jsx_runtime_1.jsx)("br", {}), (0, jsx_runtime_1.jsx)("br", {}), (0, jsx_runtime_1.jsxs)("div", { style: pre, children: ["npx remotion render ", url, " ", '<comp-name> <output-location>'] }), (0, jsx_runtime_1.jsx)("br", {}), (0, jsx_runtime_1.jsx)("br", {}), "With Remotion Lambda: ", (0, jsx_runtime_1.jsx)("br", {}), (0, jsx_runtime_1.jsx)("br", {}), (0, jsx_runtime_1.jsxs)("div", { style: pre, children: ["npx remotion lambda render ", url, " ", '<comp-name>'] }), (0, jsx_runtime_1.jsx)("br", {}), (0, jsx_runtime_1.jsxs)("p", { children: ["You can also render still images, and use the Node.JS APIs", ' ', (0, jsx_runtime_1.jsx)("code", { children: "getCompositions()" }), ", ", (0, jsx_runtime_1.jsx)("code", { children: "renderMedia()" }), ",", ' ', (0, jsx_runtime_1.jsx)("code", { children: "renderMediaOnLambda()" }), ", ", (0, jsx_runtime_1.jsx)("code", { children: "renderStill()" }), " and", ' ', (0, jsx_runtime_1.jsx)("code", { children: "renderStillOnLambda()" }), " with this URL."] }), (0, jsx_runtime_1.jsxs)("p", { children: ["Visit", ' ', (0, jsx_runtime_1.jsx)("a", { href: "https://remotion.dev/docs", target: "_blank", children: "remotion.dev/docs" }), ' ', "to read the documentation."] })] }));
|
|
62
61
|
};
|
|
63
62
|
exports.Homepage = Homepage;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import esbuild = require('esbuild');
|
|
2
|
+
import webpack = require('webpack');
|
|
2
3
|
export declare const BundlerInternals: {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
esbuild: typeof esbuild;
|
|
5
|
+
webpackConfig: ({ entry, userDefinedComponent, outDir, environment, webpackOverride, onProgressUpdate, enableCaching, inputProps, envVariables, maxTimelineTracks, entryPoints, }: {
|
|
6
|
+
entry: string;
|
|
7
|
+
userDefinedComponent: string;
|
|
8
|
+
outDir: string;
|
|
9
|
+
environment: "development" | "production";
|
|
10
|
+
webpackOverride: import("remotion").WebpackOverrideFn;
|
|
11
|
+
onProgressUpdate?: ((f: number) => void) | undefined;
|
|
12
|
+
enableCaching?: boolean | undefined;
|
|
13
|
+
inputProps: object;
|
|
14
|
+
envVariables: Record<string, string>;
|
|
15
|
+
maxTimelineTracks: number;
|
|
16
|
+
entryPoints: string[];
|
|
17
|
+
}) => webpack.Configuration;
|
|
18
|
+
indexHtml: (staticHash: string, baseDir: string, editorName: string | null) => string;
|
|
10
19
|
cacheExists: (environment: "development" | "production", inputProps: object | null) => boolean;
|
|
11
20
|
clearCache: (environment: "development" | "production", inputProps: object | null) => Promise<void>;
|
|
12
|
-
getLatestRemotionVersion: () => Promise<any>;
|
|
13
|
-
getPackageManager: () => import("./get-package-manager").PackageManager | "unknown";
|
|
14
|
-
lockFilePaths: {
|
|
15
|
-
manager: import("./get-package-manager").PackageManager;
|
|
16
|
-
path: string;
|
|
17
|
-
}[];
|
|
18
|
-
esbuild: typeof esbuild;
|
|
19
21
|
};
|
|
20
22
|
export { bundle } from './bundle';
|
|
21
|
-
export {
|
|
22
|
-
export type { ProjectInfo } from './project-info';
|
|
23
|
+
export { webpack };
|
package/dist/index.js
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.bundle = exports.BundlerInternals = void 0;
|
|
4
|
-
const
|
|
5
|
-
const get_package_manager_1 = require("./get-package-manager");
|
|
6
|
-
const start_server_1 = require("./start-server");
|
|
3
|
+
exports.webpack = exports.bundle = exports.BundlerInternals = void 0;
|
|
4
|
+
const index_html_1 = require("./index-html");
|
|
7
5
|
const webpack_cache_1 = require("./webpack-cache");
|
|
6
|
+
const webpack_config_1 = require("./webpack-config");
|
|
8
7
|
const esbuild = require("esbuild");
|
|
8
|
+
const webpack = require("webpack");
|
|
9
|
+
exports.webpack = webpack;
|
|
9
10
|
exports.BundlerInternals = {
|
|
10
|
-
|
|
11
|
+
esbuild,
|
|
12
|
+
webpackConfig: webpack_config_1.webpackConfig,
|
|
13
|
+
indexHtml: index_html_1.indexHtml,
|
|
11
14
|
cacheExists: webpack_cache_1.cacheExists,
|
|
12
15
|
clearCache: webpack_cache_1.clearCache,
|
|
13
|
-
getLatestRemotionVersion: get_latest_remotion_version_1.getLatestRemotionVersion,
|
|
14
|
-
getPackageManager: get_package_manager_1.getPackageManager,
|
|
15
|
-
lockFilePaths: get_package_manager_1.lockFilePaths,
|
|
16
|
-
esbuild,
|
|
17
16
|
};
|
|
18
17
|
var bundle_1 = require("./bundle");
|
|
19
18
|
Object.defineProperty(exports, "bundle", { enumerable: true, get: function () { return bundle_1.bundle; } });
|
package/dist/renderEntry.js
CHANGED
|
@@ -15,16 +15,14 @@ const remotion_1 = require("remotion");
|
|
|
15
15
|
const bundle_mode_1 = require("./bundle-mode");
|
|
16
16
|
const homepage_1 = require("./homepage/homepage");
|
|
17
17
|
remotion_1.Internals.CSSUtils.injectCSS(remotion_1.Internals.CSSUtils.makeDefaultCSS(null, '#fff'));
|
|
18
|
-
const Root = remotion_1.Internals.getRoot();
|
|
19
|
-
if (!Root) {
|
|
20
|
-
throw new Error('Root has not been registered.');
|
|
21
|
-
}
|
|
22
|
-
const handle = (0, remotion_1.delayRender)('Loading root component');
|
|
23
18
|
const GetVideo = ({ state }) => {
|
|
24
19
|
const video = remotion_1.Internals.useVideo();
|
|
25
20
|
const compositions = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
|
|
26
|
-
const [Component, setComponent] = (0, react_1.useState)(null);
|
|
27
21
|
const portalContainer = (0, react_1.useRef)(null);
|
|
22
|
+
const [handle] = (0, react_1.useState)(() => (0, remotion_1.delayRender)('Wait for Composition' + JSON.stringify(state)));
|
|
23
|
+
(0, react_1.useEffect)(() => {
|
|
24
|
+
return () => (0, remotion_1.continueRender)(handle);
|
|
25
|
+
}, [handle]);
|
|
28
26
|
(0, react_1.useEffect)(() => {
|
|
29
27
|
var _a;
|
|
30
28
|
if (state.type !== 'composition') {
|
|
@@ -38,26 +36,14 @@ const GetVideo = ({ state }) => {
|
|
|
38
36
|
compositions.setCurrentComposition((_a = foundComposition === null || foundComposition === void 0 ? void 0 : foundComposition.id) !== null && _a !== void 0 ? _a : null);
|
|
39
37
|
}
|
|
40
38
|
}, [compositions, compositions.compositions, state, video]);
|
|
41
|
-
const fetchComponent = (0, react_1.useCallback)(() => {
|
|
42
|
-
if (!video) {
|
|
43
|
-
throw new Error('Expected to have video');
|
|
44
|
-
}
|
|
45
|
-
const Comp = video.component;
|
|
46
|
-
setComponent(Comp);
|
|
47
|
-
}, [video]);
|
|
48
|
-
(0, react_1.useEffect)(() => {
|
|
49
|
-
if (video) {
|
|
50
|
-
fetchComponent();
|
|
51
|
-
}
|
|
52
|
-
}, [fetchComponent, video]);
|
|
53
39
|
(0, react_1.useEffect)(() => {
|
|
54
40
|
if (state.type === 'evaluation') {
|
|
55
41
|
(0, remotion_1.continueRender)(handle);
|
|
56
42
|
}
|
|
57
|
-
else if (
|
|
43
|
+
else if (video) {
|
|
58
44
|
(0, remotion_1.continueRender)(handle);
|
|
59
45
|
}
|
|
60
|
-
}, [
|
|
46
|
+
}, [handle, state.type, video]);
|
|
61
47
|
(0, react_1.useEffect)(() => {
|
|
62
48
|
if (!video) {
|
|
63
49
|
return;
|
|
@@ -89,10 +75,28 @@ let cleanupVideoContainer = () => {
|
|
|
89
75
|
let cleanupExplainerContainer = () => {
|
|
90
76
|
explainerContainer.innerHTML = '';
|
|
91
77
|
};
|
|
78
|
+
const waitForRootHandle = (0, remotion_1.delayRender)('Loading root component');
|
|
79
|
+
const WaitForRoot = () => {
|
|
80
|
+
const [Root, setRoot] = (0, react_1.useState)(() => remotion_1.Internals.getRoot());
|
|
81
|
+
(0, react_1.useEffect)(() => {
|
|
82
|
+
if (Root) {
|
|
83
|
+
(0, remotion_1.continueRender)(waitForRootHandle);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const cleanup = remotion_1.Internals.waitForRoot((NewRoot) => {
|
|
87
|
+
setRoot(() => NewRoot);
|
|
88
|
+
});
|
|
89
|
+
return () => cleanup();
|
|
90
|
+
}, [Root]);
|
|
91
|
+
if (Root === null) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
return (0, jsx_runtime_1.jsx)(Root, {});
|
|
95
|
+
};
|
|
92
96
|
const renderContent = () => {
|
|
93
97
|
const bundleMode = (0, bundle_mode_1.getBundleMode)();
|
|
94
98
|
if (bundleMode.type === 'composition' || bundleMode.type === 'evaluation') {
|
|
95
|
-
const markup = ((0, jsx_runtime_1.jsxs)(remotion_1.Internals.RemotionRoot, { children: [(0, jsx_runtime_1.jsx)(
|
|
99
|
+
const markup = ((0, jsx_runtime_1.jsxs)(remotion_1.Internals.RemotionRoot, { children: [(0, jsx_runtime_1.jsx)(WaitForRoot, {}), (0, jsx_runtime_1.jsx)(GetVideo, { state: bundleMode })] }));
|
|
96
100
|
if (client_1.default.createRoot) {
|
|
97
101
|
const root = client_1.default.createRoot(videoContainer);
|
|
98
102
|
root.render(markup);
|
|
@@ -144,6 +148,9 @@ const setBundleModeAndUpdate = (state) => {
|
|
|
144
148
|
exports.setBundleModeAndUpdate = setBundleModeAndUpdate;
|
|
145
149
|
if (typeof window !== 'undefined') {
|
|
146
150
|
window.getStaticCompositions = () => {
|
|
151
|
+
if (!remotion_1.Internals.getRoot()) {
|
|
152
|
+
throw new Error('registerRoot() was never called. 1. Make sure you specified the correct entrypoint for your bundle. 2. If your registerRoot() call is deferred, use the delayRender/continueRender pattern to tell Remotion to wait.');
|
|
153
|
+
}
|
|
147
154
|
if (!remotion_1.Internals.compositionsRef.current) {
|
|
148
155
|
throw new Error('Unexpectedly did not have a CompositionManager');
|
|
149
156
|
}
|
package/dist/webpack-config.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { WebpackConfiguration, WebpackOverrideFn } from 'remotion';
|
|
2
|
-
export declare const webpackConfig: ({ entry, userDefinedComponent, outDir, environment, webpackOverride, onProgressUpdate, enableCaching, inputProps, envVariables, maxTimelineTracks, }: {
|
|
2
|
+
export declare const webpackConfig: ({ entry, userDefinedComponent, outDir, environment, webpackOverride, onProgressUpdate, enableCaching, inputProps, envVariables, maxTimelineTracks, entryPoints, }: {
|
|
3
3
|
entry: string;
|
|
4
4
|
userDefinedComponent: string;
|
|
5
5
|
outDir: string;
|
|
@@ -10,4 +10,5 @@ export declare const webpackConfig: ({ entry, userDefinedComponent, outDir, envi
|
|
|
10
10
|
inputProps: object;
|
|
11
11
|
envVariables: Record<string, string>;
|
|
12
12
|
maxTimelineTracks: number;
|
|
13
|
+
entryPoints: string[];
|
|
13
14
|
}) => WebpackConfiguration;
|
package/dist/webpack-config.js
CHANGED
|
@@ -27,7 +27,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
29
|
exports.webpackConfig = void 0;
|
|
30
|
-
const path_1 = __importDefault(require("path"));
|
|
31
30
|
const react_dom_1 = __importDefault(require("react-dom"));
|
|
32
31
|
const remotion_1 = require("remotion");
|
|
33
32
|
const webpack_1 = __importStar(require("webpack"));
|
|
@@ -50,7 +49,7 @@ const esbuildLoaderOptions = {
|
|
|
50
49
|
function truthy(value) {
|
|
51
50
|
return Boolean(value);
|
|
52
51
|
}
|
|
53
|
-
const webpackConfig = ({ entry, userDefinedComponent, outDir, environment, webpackOverride = (f) => f, onProgressUpdate, enableCaching = remotion_1.Internals.DEFAULT_WEBPACK_CACHE_ENABLED, inputProps, envVariables, maxTimelineTracks, }) => {
|
|
52
|
+
const webpackConfig = ({ entry, userDefinedComponent, outDir, environment, webpackOverride = (f) => f, onProgressUpdate, enableCaching = remotion_1.Internals.DEFAULT_WEBPACK_CACHE_ENABLED, inputProps, envVariables, maxTimelineTracks, entryPoints, }) => {
|
|
54
53
|
return webpackOverride({
|
|
55
54
|
optimization: {
|
|
56
55
|
minimize: false,
|
|
@@ -76,16 +75,14 @@ const webpackConfig = ({ entry, userDefinedComponent, outDir, environment, webpa
|
|
|
76
75
|
? 'cheap-module-source-map'
|
|
77
76
|
: 'cheap-module-source-map',
|
|
78
77
|
entry: [
|
|
79
|
-
|
|
80
|
-
environment
|
|
81
|
-
|
|
82
|
-
: null,
|
|
78
|
+
// Fast Refresh must come first,
|
|
79
|
+
// because setup-environment imports ReactDOM.
|
|
80
|
+
// If React DOM is imported before Fast Refresh, Fast Refresh does not work
|
|
83
81
|
environment === 'development'
|
|
84
82
|
? require.resolve('./fast-refresh/runtime.js')
|
|
85
83
|
: null,
|
|
86
|
-
environment
|
|
87
|
-
|
|
88
|
-
: null,
|
|
84
|
+
require.resolve('./setup-environment'),
|
|
85
|
+
...entryPoints,
|
|
89
86
|
userDefinedComponent,
|
|
90
87
|
require.resolve('../react-shim.js'),
|
|
91
88
|
entry,
|
|
@@ -116,11 +113,6 @@ const webpackConfig = ({ entry, userDefinedComponent, outDir, environment, webpa
|
|
|
116
113
|
devtoolModuleFilenameTemplate: '[resource-path]',
|
|
117
114
|
assetModuleFilename: environment === 'development' ? '[path][name][ext]' : '[hash][ext]',
|
|
118
115
|
},
|
|
119
|
-
devServer: {
|
|
120
|
-
contentBase: path_1.default.resolve(__dirname, '..', 'web'),
|
|
121
|
-
historyApiFallback: true,
|
|
122
|
-
hot: true,
|
|
123
|
-
},
|
|
124
116
|
resolve: {
|
|
125
117
|
extensions: ['.ts', '.tsx', '.js', '.jsx'],
|
|
126
118
|
alias: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remotion/bundler",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.22",
|
|
4
4
|
"description": "Bundler for Remotion",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
},
|
|
13
13
|
"scripts": {
|
|
14
14
|
"lint": "eslint src --ext ts,tsx",
|
|
15
|
-
"test": "jest",
|
|
16
15
|
"build": "tsc -d",
|
|
17
16
|
"watch": "tsc -w"
|
|
18
17
|
},
|
|
@@ -26,13 +25,8 @@
|
|
|
26
25
|
"dependencies": {
|
|
27
26
|
"css-loader": "5.2.7",
|
|
28
27
|
"esbuild": "0.14.19",
|
|
29
|
-
"express": "4.17.1",
|
|
30
|
-
"memfs": "3.4.3",
|
|
31
|
-
"mime-types": "2.1.34",
|
|
32
28
|
"react-refresh": "0.9.0",
|
|
33
|
-
"remotion": "3.0.
|
|
34
|
-
"semver": "7.3.4",
|
|
35
|
-
"source-map": "0.6.1",
|
|
29
|
+
"remotion": "3.0.22",
|
|
36
30
|
"style-loader": "2.0.0",
|
|
37
31
|
"webpack": "5.72.0"
|
|
38
32
|
},
|
|
@@ -42,13 +36,9 @@
|
|
|
42
36
|
},
|
|
43
37
|
"devDependencies": {
|
|
44
38
|
"@jonny/eslint-config": "3.0.259",
|
|
45
|
-
"@types/express": "^4.17.7",
|
|
46
|
-
"@types/jest": "^27.4.0",
|
|
47
|
-
"@types/mime-types": "2.1.1",
|
|
48
39
|
"@types/node": "^16.7.5",
|
|
49
40
|
"@types/react": "18.0.1",
|
|
50
41
|
"@types/react-dom": "18.0.0",
|
|
51
|
-
"@types/semver": "^7.3.4",
|
|
52
42
|
"@types/webpack-env": "^1.16.0",
|
|
53
43
|
"@typescript-eslint/eslint-plugin": "5.18.0",
|
|
54
44
|
"@typescript-eslint/parser": "5.18.0",
|
|
@@ -56,12 +46,10 @@
|
|
|
56
46
|
"eslint-plugin-10x": "1.5.2",
|
|
57
47
|
"eslint-plugin-react": "7.29.4",
|
|
58
48
|
"eslint-plugin-react-hooks": "4.4.0",
|
|
59
|
-
"jest": "^27.2.4",
|
|
60
49
|
"prettier": "^2.0.5",
|
|
61
50
|
"prettier-plugin-organize-imports": "^2.3.4",
|
|
62
51
|
"react": "^18.0.0",
|
|
63
52
|
"react-dom": "^18.0.0",
|
|
64
|
-
"ts-jest": "^27.0.5",
|
|
65
53
|
"typescript": "^4.7.0"
|
|
66
54
|
},
|
|
67
55
|
"keywords": [
|
|
@@ -75,5 +63,5 @@
|
|
|
75
63
|
"publishConfig": {
|
|
76
64
|
"access": "public"
|
|
77
65
|
},
|
|
78
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "e79cfa299f58a26c84a637174875941898cdab97"
|
|
79
67
|
}
|
package/web/favicon.png
DELETED
|
Binary file
|