├── .github
└── FUNDING.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── package.json
├── pnpm-lock.yaml
├── src
└── index.ts
├── tsconfig.json
└── vercel.json
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: cupcakearmy
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | .vscode
4 | docs
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | ## [Unreleased]
9 |
10 | ## [0.2.5] - 2021-12-26
11 |
12 | ### Changed
13 |
14 | - Updated docs.
15 | - remove `lodash` as dependency.
16 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Niccolo Borgioli
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | > DEPRECATED
2 | >
3 | > See https://github.com/cloudinary-community/svelte-cloudinary
4 | >
5 | > The npm package will be transfered to them.
6 |
7 | # svelte-cloudinary
8 |
9 | 
10 | 
11 | 
12 | 
13 | 
14 |
15 | This is a little library that aims at integrating and making it easier to use the svelte with [Cloudinary](https://cloudinary.com/).
16 | There is an [official integration coming](https://github.com/cloudinary/cloudinary-svelte), but it's not ready and for not does not work great for now (SSR e.g.).
17 |
18 | ## 🌈 Features
19 |
20 | - Fully typed and typescript compatible
21 | - [Tiny: `~30kb gzip`](https://bundlephobia.com/result?p=svelte-cloudinary) (Of which 99% is the cloudinary dep.)
22 | - Automatic **resizing** based on the DOM and applied CSS
23 | - Automatic **lazy loading**
24 | - Fully compatible with native cloudinary options
25 | - Sapper (SSR) compatible
26 |
27 | ## 🗂 [Docs](https://svelte-cloudinary.vercel.app/modules/_index_)
28 |
29 | ## ❓ Questions & More -> [Discussions](https://github.com/cupcakearmy/svelte-cloudinary/discussions)
30 |
31 | ## 🚀 Quickstart
32 |
33 | ```bash
34 | npm install svelte-cloudinary
35 | ```
36 |
37 | ```svelte
38 |
46 |
47 |
54 |
55 |
59 | ```
60 |
61 | This will formulate the Cloudinary url and insert it into the `img.src` property.
62 | Also it will resize to the `img` object itself because we set `bind: true`.
63 |
64 | > ⚠️ In firefox if you want to use the `bind` option to automatically compute sizes you need to set `img { display: inline-block or block; }` otherwise there can be problems with `getComputedStyle`.
65 |
66 | ## ☁️ Cloudinary Setup
67 |
68 | If you want the use super handfull auto upload function (which I think will apply to everyone) you have to set configure a few settings first.
69 |
70 | - Settings -> Security -> Allowed fetch domains: Add your domain(s) from which the images are fetched from.
71 | - Settings -> Upload -> Auto upload mapping: Set the mapping for your domain and/or path
72 |
73 | ###### Example
74 |
75 | Immagine you want to serve an image with the url of: `https://api.example.org/images/elephants.png`
76 |
77 | 1. Settings -> Security -> Allowed fetch domains: Add `api.example.org` to the list.
78 | 2. Settings -> Upload -> Auto upload mapping:
Folder: `myimages`
URL prefix: `https://api.example.org/images/`
79 |
80 | Now you can use the auto upload funtion like this:
81 |
82 | ```svelte
83 |
87 | ```
88 |
89 | ## 🤔 Why an [action](https://svelte.dev/docs#use_action) and not component?
90 |
91 | Well components are great of course, but when we only need to set a `src` tags we can leverage the upsides of a svelte [action](https://svelte.dev/docs#use_action)
92 |
93 | What are benefits?
94 |
95 | - Native styling (Svelte for now does not allow easy styling of child components)
With an action we can easily use local styling beacuse we still have access to the `
` element
96 | - Lightweight
97 | - Reusable and composable
98 |
99 | Downsides:
100 |
101 | - The src will not be set serverside, so also not in the initial server response. Which I believe is not that bad though for images.
102 |
103 | ## 👷 Sapper
104 |
105 | If you are using sapper you can initialize it once in your root `_layout.svelte`.
106 |
107 | ```svelte
108 |
115 | ```
116 |
117 | ## 🤓 Key Concepts
118 |
119 | ### `lazy`
120 |
121 | ###### default `true`
122 |
123 | If images should use the [`Intersection Observer API`](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) to lazy load.
124 |
125 | ### `step`
126 |
127 | ###### default `200`
128 |
129 | The `step` property helps reducing the amounts of transformations cloudinary need to perform and less credits being billed to you.
130 |
131 | How? Basically whenever we calculate the dynamic size of the image rendered on the DOM we will get very specific numbers depending on the device.
132 |
133 | With `step` we approximate the size needed to the nearset bigger multiple of `step`.
134 |
135 | ###### Example
136 |
137 | Imagine the same `
` has the width of `420`,`470` and `1080` on an iPhone, Android and Laptop respectively.
138 |
139 | With a `step` size of e.g. `100` (`
`) they will become `500`, `500`, and `1100`. This will limit the ammount of transformations needed.
140 |
141 | ### `bind`
142 |
143 | With bind we can dynamically set the width and/or height of the transformed image depending of the rendered size.
144 |
145 | - `bind: this` The size of the `
` element
146 | - `bind: el` The computed size of another element in the dom (useful for a carousel e.g.)
147 | - `bind: { width: this }` Only bind the width, leaving the height free. Also works with height of course
148 | - `bind: { width: '.wrapper' }` Finds the closest element that matches the selector and uses it for width.
149 |
150 | ##### Note
151 |
152 | If you provide a `bind` options (`
`) but no crop option, we will automatically add `crop: 'fill'` otherwise the image will not be resized by cloudinary.
153 |
154 | ###### TLDR;
155 |
156 | ```svelte
157 |
158 |
159 |
160 | ```
161 |
162 | ## ⌨️ Examples
163 |
164 | ### Fixed size
165 |
166 | ```svelte
167 |
170 | ```
171 |
172 | ### `bind`
173 |
174 | ```svelte
175 |
176 |
179 | ```
180 |
181 | ```svelte
182 |
183 |
187 |
188 | ```
189 |
190 | ```svelte
191 |
192 |
196 |
197 | ```
198 |
199 | ### `options`
200 |
201 | Native cloudinary options. See [here for official docs](https://cloudinary.com/documentation/image_transformations)
202 | For a quick glance
203 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "svelte-cloudinary",
3 | "version": "0.2.5",
4 | "main": "./dist/index.js",
5 | "types": "./dist/index.d.ts",
6 | "files": [
7 | "dist"
8 | ],
9 | "scripts": {
10 | "dev": "tsc -w",
11 | "build": "tsc",
12 | "prepublishOnly": "rm -rf dist && pnpm run build",
13 | "docs": "typedoc --out docs src"
14 | },
15 | "devDependencies": {
16 | "typedoc": "^0.22.10",
17 | "typescript": "^4.5.4"
18 | },
19 | "dependencies": {
20 | "cloudinary-core": "^2.12.0"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: 5.3
2 |
3 | specifiers:
4 | cloudinary-core: ^2.12.0
5 | typedoc: ^0.22.10
6 | typescript: ^4.5.4
7 |
8 | dependencies:
9 | cloudinary-core: 2.12.0
10 |
11 | devDependencies:
12 | typedoc: 0.22.10_typescript@4.5.4
13 | typescript: 4.5.4
14 |
15 | packages:
16 |
17 | /balanced-match/1.0.2:
18 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
19 | dev: true
20 |
21 | /brace-expansion/1.1.11:
22 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
23 | dependencies:
24 | balanced-match: 1.0.2
25 | concat-map: 0.0.1
26 | dev: true
27 |
28 | /cloudinary-core/2.12.0:
29 | resolution: {integrity: sha512-EXvnWuq3Ah6pZHB2vEfkrJ4tCGlccZo3xsmt1f+bmrB53jU42ZrnX+v8xKRMot9c/STSO7GPbxbhJQ/z/xRazg==}
30 | peerDependencies:
31 | lodash: '>=4.0'
32 | dev: false
33 |
34 | /concat-map/0.0.1:
35 | resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
36 | dev: true
37 |
38 | /fs.realpath/1.0.0:
39 | resolution: {integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=}
40 | dev: true
41 |
42 | /glob/7.2.0:
43 | resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==}
44 | dependencies:
45 | fs.realpath: 1.0.0
46 | inflight: 1.0.6
47 | inherits: 2.0.4
48 | minimatch: 3.0.4
49 | once: 1.4.0
50 | path-is-absolute: 1.0.1
51 | dev: true
52 |
53 | /inflight/1.0.6:
54 | resolution: {integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=}
55 | dependencies:
56 | once: 1.4.0
57 | wrappy: 1.0.2
58 | dev: true
59 |
60 | /inherits/2.0.4:
61 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
62 | dev: true
63 |
64 | /jsonc-parser/3.0.0:
65 | resolution: {integrity: sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==}
66 | dev: true
67 |
68 | /lunr/2.3.9:
69 | resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==}
70 | dev: true
71 |
72 | /marked/3.0.8:
73 | resolution: {integrity: sha512-0gVrAjo5m0VZSJb4rpL59K1unJAMb/hm8HRXqasD8VeC8m91ytDPMritgFSlKonfdt+rRYYpP/JfLxgIX8yoSw==}
74 | engines: {node: '>= 12'}
75 | hasBin: true
76 | dev: true
77 |
78 | /minimatch/3.0.4:
79 | resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==}
80 | dependencies:
81 | brace-expansion: 1.1.11
82 | dev: true
83 |
84 | /once/1.4.0:
85 | resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=}
86 | dependencies:
87 | wrappy: 1.0.2
88 | dev: true
89 |
90 | /path-is-absolute/1.0.1:
91 | resolution: {integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18=}
92 | engines: {node: '>=0.10.0'}
93 | dev: true
94 |
95 | /shiki/0.9.15:
96 | resolution: {integrity: sha512-/Y0z9IzhJ8nD9nbceORCqu6NgT9X6I8Fk8c3SICHI5NbZRLdZYFaB233gwct9sU0vvSypyaL/qaKvzyQGJBZSw==}
97 | dependencies:
98 | jsonc-parser: 3.0.0
99 | vscode-oniguruma: 1.6.1
100 | vscode-textmate: 5.2.0
101 | dev: true
102 |
103 | /typedoc/0.22.10_typescript@4.5.4:
104 | resolution: {integrity: sha512-hQYZ4WtoMZ61wDC6w10kxA42+jclWngdmztNZsDvIz7BMJg7F2xnT+uYsUa7OluyKossdFj9E9Ye4QOZKTy8SA==}
105 | engines: {node: '>= 12.10.0'}
106 | hasBin: true
107 | peerDependencies:
108 | typescript: 4.0.x || 4.1.x || 4.2.x || 4.3.x || 4.4.x || 4.5.x
109 | dependencies:
110 | glob: 7.2.0
111 | lunr: 2.3.9
112 | marked: 3.0.8
113 | minimatch: 3.0.4
114 | shiki: 0.9.15
115 | typescript: 4.5.4
116 | dev: true
117 |
118 | /typescript/4.5.4:
119 | resolution: {integrity: sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==}
120 | engines: {node: '>=4.2.0'}
121 | hasBin: true
122 | dev: true
123 |
124 | /vscode-oniguruma/1.6.1:
125 | resolution: {integrity: sha512-vc4WhSIaVpgJ0jJIejjYxPvURJavX6QG41vu0mGhqywMkQqulezEqEQ3cO3gc8GvcOpX6ycmKGqRoROEMBNXTQ==}
126 | dev: true
127 |
128 | /vscode-textmate/5.2.0:
129 | resolution: {integrity: sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==}
130 | dev: true
131 |
132 | /wrappy/1.0.2:
133 | resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=}
134 | dev: true
135 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import { Cloudinary, Configuration, Transformation } from 'cloudinary-core'
2 |
3 | export type ElementOrString = HTMLElement | string
4 | export type Size = { width: number; height: number }
5 | export type BindType = ElementOrString | true
6 | export type BindObject = BindType | { width?: BindType; height?: BindType }
7 |
8 | export type InitParameters = { debug?: boolean }
9 | export type ImageParameters = {
10 | src: string
11 | options?: Transformation | Transformation.Options
12 | bind?: BindObject
13 | lazy?: boolean | IntersectionObserverInit
14 | step?: number
15 | }
16 |
17 | let cl: Cloudinary | null = null
18 | let DEBUG: boolean = false
19 |
20 | function log(...msg: any[]) {
21 | if (DEBUG) console.debug(...msg)
22 | }
23 |
24 | export function initialize(cloudinary: Configuration.Options, options: InitParameters = {}) {
25 | DEBUG = options.debug || false
26 | cl = Cloudinary.new(cloudinary)
27 | }
28 |
29 | const defaults: Transformation | Transformation.Options = {
30 | fetchFormat: 'auto',
31 | quality: 'auto',
32 | }
33 |
34 | function calculateApproxRealSize(size: string, step: number): number {
35 | const withRatio = (parseInt(size) * window.devicePixelRatio) | 0
36 | const approx = withRatio - (withRatio % step) + step
37 | log(`Size\t withRation=${withRatio} approx=${approx} step=${step}`)
38 | return approx
39 | }
40 |
41 | function getSizeOfElement(el: HTMLElement, step: number): Size {
42 | const styles = window.getComputedStyle(el)
43 | log('GetSizeOfElement', el, `width=${styles.width} height=${styles.height}`)
44 | return {
45 | width: calculateApproxRealSize(styles.width, step),
46 | height: calculateApproxRealSize(styles.height, step),
47 | }
48 | }
49 |
50 | function getSizeOfElementOrSelector(node: ElementOrString, elOrString: ElementOrString, step: number): Size {
51 | if (typeof elOrString === 'string') {
52 | const search = typeof node === 'string' ? window.document.querySelector(node) : node
53 | if (!search) throw new Error('Could not find element: ' + node)
54 | const closest = search.closest(elOrString)
55 | if (closest) return getSizeOfElement(closest, step)
56 | else throw new Error('Could not find element: ' + elOrString)
57 | } else {
58 | return getSizeOfElement(elOrString, step)
59 | }
60 | }
61 |
62 | export function image(node: HTMLImageElement, parameters: ImageParameters) {
63 | if (!parameters || !parameters.src) throw new Error('No url provided for cloudinary')
64 |
65 | let { src, options, bind, lazy, step } = parameters
66 | log('Image Declared', parameters)
67 | options = options ?? {}
68 | options.crop = options.crop ?? 'fill'
69 | step = step ?? 200
70 | lazy = lazy ?? true
71 |
72 | if (!cl) throw new Error('Cloudinary not initialized')
73 | if (!src) throw new Error('Src must be set in use:image')
74 |
75 | if (bind) {
76 | if (bind === true) {
77 | bind = node
78 | }
79 | if (!options.crop) options.crop = 'fill'
80 |
81 | if (bind instanceof Element) Object.assign(options, getSizeOfElement(bind, step))
82 | else if (typeof bind === 'string') {
83 | Object.assign(options, getSizeOfElementOrSelector(node, bind, step))
84 | } else if (typeof bind === 'object') {
85 | if (bind.width) {
86 | options.width = getSizeOfElementOrSelector(node, bind.width === true ? node : bind.width, step).width
87 | }
88 | if (bind.height) {
89 | options.height = getSizeOfElementOrSelector(node, bind.height === true ? node : bind.height, step).height
90 | }
91 | }
92 | }
93 |
94 | const all: Transformation | Transformation.Options = { ...defaults, ...options }
95 | const attrs: any = cl.imageTag(parameters.src, all).attributes()
96 | log('Attributes', attrs)
97 | const replace = () => (node.src = attrs.src)
98 |
99 | if (lazy && typeof IntersectionObserver !== 'undefined') {
100 | const options: IntersectionObserverInit = lazy === true ? { rootMargin: '25%', threshold: 0 } : lazy
101 | new IntersectionObserver((entries, observer) => {
102 | if (entries[0].isIntersecting) {
103 | observer.disconnect()
104 | replace()
105 | }
106 | }, options).observe(node)
107 | } else {
108 | replace()
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */
4 |
5 | /* Basic Options */
6 | // "incremental": true, /* Enable incremental compilation */
7 | "target": "es2018", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
8 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
9 | // "lib": [], /* Specify library files to be included in the compilation. */
10 | // "allowJs": true, /* Allow javascript files to be compiled. */
11 | // "checkJs": true, /* Report errors in .js files. */
12 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
13 | "declaration": true, /* Generates corresponding '.d.ts' file. */
14 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
15 | // "sourceMap": true, /* Generates corresponding '.map' file. */
16 | // "outFile": "./", /* Concatenate and emit output to single file. */
17 | "outDir": "./dist", /* Redirect output structure to the directory. */
18 | "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
19 | // "composite": true, /* Enable project compilation */
20 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
21 | // "removeComments": true, /* Do not emit comments to output. */
22 | // "noEmit": true, /* Do not emit outputs. */
23 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */
24 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
25 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
26 |
27 | /* Strict Type-Checking Options */
28 | "strict": true, /* Enable all strict type-checking options. */
29 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
30 | // "strictNullChecks": true, /* Enable strict null checks. */
31 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */
32 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
33 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
34 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
35 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
36 |
37 | /* Additional Checks */
38 | // "noUnusedLocals": true, /* Report errors on unused locals. */
39 | // "noUnusedParameters": true, /* Report errors on unused parameters. */
40 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
41 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
42 |
43 | /* Module Resolution Options */
44 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
45 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
46 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
47 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
48 | // "typeRoots": [], /* List of folders to include type definitions from. */
49 | // "types": [], /* Type declaration files to be included in compilation. */
50 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
51 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
52 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
53 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
54 |
55 | /* Source Map Options */
56 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
57 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
58 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
59 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
60 |
61 | /* Experimental Options */
62 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
63 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
64 |
65 | /* Advanced Options */
66 | "skipLibCheck": true, /* Skip type checking of declaration files. */
67 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/vercel.json:
--------------------------------------------------------------------------------
1 | {
2 | "cleanUrls": true
3 | }
4 |
--------------------------------------------------------------------------------