@docusaurus/plugin-ideal-image 2.0.0-beta.13 → 2.0.0-beta.15
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/lib/index.d.ts +3 -2
- package/lib/index.js +28 -5
- package/lib/theme/IdealImage/index.js +67 -0
- package/package.json +15 -6
- package/src/deps.d.ts +13 -2
- package/src/index.ts +40 -7
- package/src/plugin-ideal-image.d.ts +4 -0
- package/src/theme/IdealImage/index.tsx +73 -1
- package/tsconfig.browser.json +0 -8
- package/tsconfig.json +0 -9
- package/tsconfig.server.json +0 -4
package/lib/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
import { LoadContext, Plugin } from '@docusaurus/types';
|
|
7
|
+
import type { LoadContext, Plugin, OptionValidationContext, ValidationResult } from '@docusaurus/types';
|
|
8
8
|
import type { PluginOptions } from '@docusaurus/plugin-ideal-image';
|
|
9
|
-
export default function (
|
|
9
|
+
export default function pluginIdealImage(context: LoadContext, options: PluginOptions): Plugin<void>;
|
|
10
|
+
export declare function validateOptions({ validate, options, }: OptionValidationContext<PluginOptions>): ValidationResult<PluginOptions>;
|
package/lib/index.js
CHANGED
|
@@ -6,16 +6,32 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, '__esModule', {value: true});
|
|
9
|
+
exports.validateOptions = void 0;
|
|
9
10
|
const tslib_1 = require('tslib');
|
|
11
|
+
const utils_validation_1 = require('@docusaurus/utils-validation');
|
|
12
|
+
const theme_translations_1 = require('@docusaurus/theme-translations');
|
|
10
13
|
const path_1 = (0, tslib_1.__importDefault)(require('path'));
|
|
11
|
-
function
|
|
14
|
+
function pluginIdealImage(context, options) {
|
|
15
|
+
const {
|
|
16
|
+
i18n: {currentLocale},
|
|
17
|
+
} = context;
|
|
12
18
|
return {
|
|
13
19
|
name: 'docusaurus-plugin-ideal-image',
|
|
14
20
|
getThemePath() {
|
|
15
|
-
return path_1.default.resolve(__dirname, '
|
|
21
|
+
return path_1.default.resolve(__dirname, '../lib/theme');
|
|
22
|
+
},
|
|
23
|
+
getTypeScriptThemePath() {
|
|
24
|
+
return path_1.default.resolve(__dirname, '../src/theme');
|
|
25
|
+
},
|
|
26
|
+
getDefaultCodeTranslationMessages() {
|
|
27
|
+
return (0, theme_translations_1.readDefaultCodeTranslationMessages)({
|
|
28
|
+
locale: currentLocale,
|
|
29
|
+
name: 'plugin-ideal-image',
|
|
30
|
+
});
|
|
16
31
|
},
|
|
17
32
|
configureWebpack(_config, isServer) {
|
|
18
|
-
|
|
33
|
+
const {disableInDev, ...loaderOptions} = options;
|
|
34
|
+
if (disableInDev && process.env.NODE_ENV !== 'production') {
|
|
19
35
|
return {};
|
|
20
36
|
}
|
|
21
37
|
return {
|
|
@@ -35,7 +51,7 @@ function default_1(_context, options) {
|
|
|
35
51
|
// eslint-disable-next-line global-require
|
|
36
52
|
adapter: require('@docusaurus/responsive-loader/sharp'),
|
|
37
53
|
name: 'assets/ideal-img/[name].[hash:hex:7].[width].[ext]',
|
|
38
|
-
...
|
|
54
|
+
...loaderOptions,
|
|
39
55
|
},
|
|
40
56
|
},
|
|
41
57
|
],
|
|
@@ -46,4 +62,11 @@ function default_1(_context, options) {
|
|
|
46
62
|
},
|
|
47
63
|
};
|
|
48
64
|
}
|
|
49
|
-
exports.default =
|
|
65
|
+
exports.default = pluginIdealImage;
|
|
66
|
+
function validateOptions({validate, options}) {
|
|
67
|
+
const pluginOptionsSchema = utils_validation_1.Joi.object({
|
|
68
|
+
disableInDev: utils_validation_1.Joi.boolean().default(true),
|
|
69
|
+
}).unknown();
|
|
70
|
+
return validate(pluginOptionsSchema, options);
|
|
71
|
+
}
|
|
72
|
+
exports.validateOptions = validateOptions;
|
|
@@ -6,6 +6,72 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import React from 'react';
|
|
8
8
|
import ReactIdealImage from '@endiliey/react-ideal-image';
|
|
9
|
+
import {translate} from '@docusaurus/Translate';
|
|
10
|
+
// Adopted from https://github.com/endiliey/react-ideal-image/blob/master/src/components/helpers.js#L59-L65
|
|
11
|
+
const bytesToSize = (bytes) => {
|
|
12
|
+
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
13
|
+
if (bytes === 0) {
|
|
14
|
+
return 'n/a';
|
|
15
|
+
}
|
|
16
|
+
const scale = Math.floor(Math.log(bytes) / Math.log(1024));
|
|
17
|
+
if (scale === 0) {
|
|
18
|
+
return `${bytes} ${sizes[scale]}`;
|
|
19
|
+
}
|
|
20
|
+
return `${(bytes / 1024 ** scale).toFixed(1)} ${sizes[scale]}`;
|
|
21
|
+
};
|
|
22
|
+
// Adopted from https://github.com/endiliey/react-ideal-image/blob/master/src/components/IdealImage/index.js#L43-L75
|
|
23
|
+
const getMessage = (icon, state) => {
|
|
24
|
+
switch (icon) {
|
|
25
|
+
case 'noicon':
|
|
26
|
+
case 'loaded':
|
|
27
|
+
return null;
|
|
28
|
+
case 'loading':
|
|
29
|
+
return translate({
|
|
30
|
+
id: 'theme.IdealImageMessage.loading',
|
|
31
|
+
message: 'Loading...',
|
|
32
|
+
description: 'When the full-scale image is loading',
|
|
33
|
+
});
|
|
34
|
+
case 'load': {
|
|
35
|
+
// we can show `alt` here
|
|
36
|
+
const {pickedSrc} = state;
|
|
37
|
+
const {size} = pickedSrc;
|
|
38
|
+
const sizeMessage = size ? ` (${bytesToSize(size)})` : '';
|
|
39
|
+
return translate(
|
|
40
|
+
{
|
|
41
|
+
id: 'theme.IdealImageMessage.load',
|
|
42
|
+
message: 'Click to load{sizeMessage}',
|
|
43
|
+
description:
|
|
44
|
+
'To prompt users to load the full image. sizeMessage is a parenthesized size figure.',
|
|
45
|
+
},
|
|
46
|
+
{sizeMessage},
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
case 'offline':
|
|
50
|
+
return translate({
|
|
51
|
+
id: 'theme.IdealImageMessage.offline',
|
|
52
|
+
message: 'Your browser is offline. Image not loaded',
|
|
53
|
+
description: 'When the user is viewing an offline document',
|
|
54
|
+
});
|
|
55
|
+
case 'error': {
|
|
56
|
+
const {loadInfo} = state;
|
|
57
|
+
if (loadInfo === 404) {
|
|
58
|
+
return translate({
|
|
59
|
+
id: 'theme.IdealImageMessage.404error',
|
|
60
|
+
message: '404. Image not found',
|
|
61
|
+
description: 'When the image is not found',
|
|
62
|
+
});
|
|
63
|
+
} else {
|
|
64
|
+
return translate({
|
|
65
|
+
id: 'theme.IdealImageMessage.error',
|
|
66
|
+
message: 'Error. Click to reload',
|
|
67
|
+
description: 'When the image fails to load for unknown error',
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
default:
|
|
72
|
+
throw new Error(`Wrong icon: ${icon}`);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
9
75
|
function IdealImage(props) {
|
|
10
76
|
const {alt, className, img} = props;
|
|
11
77
|
// In dev env just use regular img with original file
|
|
@@ -32,6 +98,7 @@ function IdealImage(props) {
|
|
|
32
98
|
...image,
|
|
33
99
|
src: image.path,
|
|
34
100
|
}))}
|
|
101
|
+
getMessage={getMessage}
|
|
35
102
|
/>
|
|
36
103
|
);
|
|
37
104
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docusaurus/plugin-ideal-image",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.15",
|
|
4
4
|
"description": "Docusaurus Plugin to generate an almost ideal image (responsive, lazy-loading, and low quality placeholder).",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "src/plugin-ideal-image.d.ts",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"build": "yarn build:server && yarn build:browser && yarn build:copy && yarn build:format",
|
|
9
9
|
"build:server": "tsc --project tsconfig.server.json",
|
|
10
10
|
"build:browser": "tsc --project tsconfig.browser.json",
|
|
11
|
-
"build:copy": "node copyUntypedFiles.
|
|
11
|
+
"build:copy": "node copyUntypedFiles.mjs",
|
|
12
12
|
"build:format": "prettier --config ../../.prettierrc --write \"lib/**/*.js\""
|
|
13
13
|
},
|
|
14
14
|
"publishConfig": {
|
|
@@ -21,9 +21,11 @@
|
|
|
21
21
|
},
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@docusaurus/core": "2.0.0-beta.
|
|
25
|
-
"@docusaurus/lqip-loader": "2.0.0-beta.
|
|
24
|
+
"@docusaurus/core": "2.0.0-beta.15",
|
|
25
|
+
"@docusaurus/lqip-loader": "2.0.0-beta.15",
|
|
26
26
|
"@docusaurus/responsive-loader": "1.5.0",
|
|
27
|
+
"@docusaurus/theme-translations": "2.0.0-beta.15",
|
|
28
|
+
"@docusaurus/utils-validation": "2.0.0-beta.15",
|
|
27
29
|
"@endiliey/react-ideal-image": "^0.0.11",
|
|
28
30
|
"react-waypoint": "^10.1.0",
|
|
29
31
|
"sharp": "^0.29.1",
|
|
@@ -31,15 +33,22 @@
|
|
|
31
33
|
"webpack": "^5.61.0"
|
|
32
34
|
},
|
|
33
35
|
"devDependencies": {
|
|
34
|
-
"@docusaurus/
|
|
36
|
+
"@docusaurus/module-type-aliases": "2.0.0-beta.15",
|
|
37
|
+
"@docusaurus/types": "2.0.0-beta.15",
|
|
35
38
|
"fs-extra": "^10.0.0"
|
|
36
39
|
},
|
|
37
40
|
"peerDependencies": {
|
|
41
|
+
"jimp": "*",
|
|
38
42
|
"react": "^16.8.4 || ^17.0.0",
|
|
39
43
|
"react-dom": "^16.8.4 || ^17.0.0"
|
|
40
44
|
},
|
|
45
|
+
"peerDependenciesMeta": {
|
|
46
|
+
"jimp": {
|
|
47
|
+
"optional": true
|
|
48
|
+
}
|
|
49
|
+
},
|
|
41
50
|
"engines": {
|
|
42
51
|
"node": ">=14"
|
|
43
52
|
},
|
|
44
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "6cfad16436c07d8d11e5c2e1486dc59afd483e33"
|
|
45
54
|
}
|
package/src/deps.d.ts
CHANGED
|
@@ -5,12 +5,23 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
/// <reference types="@docusaurus/module-type-aliases" />
|
|
9
|
+
|
|
8
10
|
/**
|
|
9
11
|
* @see https://github.com/endiliey/react-ideal-image/blob/master/index.d.ts
|
|
12
|
+
* Note: the original type definition is WRONG. getIcon & getMessage receive full state object.
|
|
10
13
|
*/
|
|
11
14
|
declare module '@endiliey/react-ideal-image' {
|
|
12
15
|
export type LoadingState = 'initial' | 'loading' | 'loaded' | 'error';
|
|
13
16
|
|
|
17
|
+
export type State = {
|
|
18
|
+
pickedSrc: {
|
|
19
|
+
size: number;
|
|
20
|
+
};
|
|
21
|
+
loadInfo: 404 | null;
|
|
22
|
+
loadState: LoadingState;
|
|
23
|
+
};
|
|
24
|
+
|
|
14
25
|
export type IconKey =
|
|
15
26
|
| 'load'
|
|
16
27
|
| 'loading'
|
|
@@ -32,12 +43,12 @@ declare module '@endiliey/react-ideal-image' {
|
|
|
32
43
|
/**
|
|
33
44
|
* This function decides what icon to show based on the current state of the component.
|
|
34
45
|
*/
|
|
35
|
-
getIcon?: (state:
|
|
46
|
+
getIcon?: (state: State) => IconKey;
|
|
36
47
|
/**
|
|
37
48
|
* This function decides what message to show based on the icon (returned from getIcon prop) and
|
|
38
49
|
* the current state of the component.
|
|
39
50
|
*/
|
|
40
|
-
getMessage?: (icon: IconKey, state:
|
|
51
|
+
getMessage?: (icon: IconKey, state: State) => string;
|
|
41
52
|
/**
|
|
42
53
|
* This function is called as soon as the component enters the viewport and is used to generate urls
|
|
43
54
|
* based on width and format if props.srcSet doesn't provide src field.
|
package/src/index.ts
CHANGED
|
@@ -5,25 +5,48 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import type {
|
|
9
|
+
LoadContext,
|
|
10
|
+
Plugin,
|
|
11
|
+
OptionValidationContext,
|
|
12
|
+
ValidationResult,
|
|
13
|
+
} from '@docusaurus/types';
|
|
9
14
|
import type {PluginOptions} from '@docusaurus/plugin-ideal-image';
|
|
10
|
-
import {Configuration} from 'webpack';
|
|
15
|
+
import type {Configuration} from 'webpack';
|
|
16
|
+
import {Joi} from '@docusaurus/utils-validation';
|
|
17
|
+
import {readDefaultCodeTranslationMessages} from '@docusaurus/theme-translations';
|
|
11
18
|
|
|
12
19
|
import path from 'path';
|
|
13
20
|
|
|
14
|
-
export default function (
|
|
15
|
-
|
|
21
|
+
export default function pluginIdealImage(
|
|
22
|
+
context: LoadContext,
|
|
16
23
|
options: PluginOptions,
|
|
17
24
|
): Plugin<void> {
|
|
25
|
+
const {
|
|
26
|
+
i18n: {currentLocale},
|
|
27
|
+
} = context;
|
|
28
|
+
|
|
18
29
|
return {
|
|
19
30
|
name: 'docusaurus-plugin-ideal-image',
|
|
20
31
|
|
|
21
32
|
getThemePath() {
|
|
22
|
-
return path.resolve(__dirname, '
|
|
33
|
+
return path.resolve(__dirname, '../lib/theme');
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
getTypeScriptThemePath() {
|
|
37
|
+
return path.resolve(__dirname, '../src/theme');
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
getDefaultCodeTranslationMessages() {
|
|
41
|
+
return readDefaultCodeTranslationMessages({
|
|
42
|
+
locale: currentLocale,
|
|
43
|
+
name: 'plugin-ideal-image',
|
|
44
|
+
});
|
|
23
45
|
},
|
|
24
46
|
|
|
25
47
|
configureWebpack(_config: Configuration, isServer: boolean) {
|
|
26
|
-
|
|
48
|
+
const {disableInDev, ...loaderOptions} = options;
|
|
49
|
+
if (disableInDev && process.env.NODE_ENV !== 'production') {
|
|
27
50
|
return {};
|
|
28
51
|
}
|
|
29
52
|
|
|
@@ -44,7 +67,7 @@ export default function (
|
|
|
44
67
|
// eslint-disable-next-line global-require
|
|
45
68
|
adapter: require('@docusaurus/responsive-loader/sharp'),
|
|
46
69
|
name: 'assets/ideal-img/[name].[hash:hex:7].[width].[ext]',
|
|
47
|
-
...
|
|
70
|
+
...loaderOptions,
|
|
48
71
|
},
|
|
49
72
|
},
|
|
50
73
|
],
|
|
@@ -55,3 +78,13 @@ export default function (
|
|
|
55
78
|
},
|
|
56
79
|
};
|
|
57
80
|
}
|
|
81
|
+
|
|
82
|
+
export function validateOptions({
|
|
83
|
+
validate,
|
|
84
|
+
options,
|
|
85
|
+
}: OptionValidationContext<PluginOptions>): ValidationResult<PluginOptions> {
|
|
86
|
+
const pluginOptionsSchema = Joi.object({
|
|
87
|
+
disableInDev: Joi.boolean().default(true),
|
|
88
|
+
}).unknown();
|
|
89
|
+
return validate(pluginOptionsSchema, options);
|
|
90
|
+
}
|
|
@@ -6,10 +6,81 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import React from 'react';
|
|
9
|
-
import ReactIdealImage
|
|
9
|
+
import ReactIdealImage, {
|
|
10
|
+
type IconKey,
|
|
11
|
+
type State,
|
|
12
|
+
} from '@endiliey/react-ideal-image';
|
|
13
|
+
import {translate} from '@docusaurus/Translate';
|
|
10
14
|
|
|
11
15
|
import type {Props} from '@theme/IdealImage';
|
|
12
16
|
|
|
17
|
+
// Adopted from https://github.com/endiliey/react-ideal-image/blob/master/src/components/helpers.js#L59-L65
|
|
18
|
+
const bytesToSize = (bytes: number) => {
|
|
19
|
+
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
20
|
+
if (bytes === 0) {
|
|
21
|
+
return 'n/a';
|
|
22
|
+
}
|
|
23
|
+
const scale = Math.floor(Math.log(bytes) / Math.log(1024));
|
|
24
|
+
if (scale === 0) {
|
|
25
|
+
return `${bytes} ${sizes[scale]}`;
|
|
26
|
+
}
|
|
27
|
+
return `${(bytes / 1024 ** scale).toFixed(1)} ${sizes[scale]}`;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// Adopted from https://github.com/endiliey/react-ideal-image/blob/master/src/components/IdealImage/index.js#L43-L75
|
|
31
|
+
const getMessage = (icon: IconKey, state: State) => {
|
|
32
|
+
switch (icon) {
|
|
33
|
+
case 'noicon':
|
|
34
|
+
case 'loaded':
|
|
35
|
+
return null;
|
|
36
|
+
case 'loading':
|
|
37
|
+
return translate({
|
|
38
|
+
id: 'theme.IdealImageMessage.loading',
|
|
39
|
+
message: 'Loading...',
|
|
40
|
+
description: 'When the full-scale image is loading',
|
|
41
|
+
});
|
|
42
|
+
case 'load': {
|
|
43
|
+
// we can show `alt` here
|
|
44
|
+
const {pickedSrc} = state;
|
|
45
|
+
const {size} = pickedSrc;
|
|
46
|
+
const sizeMessage = size ? ` (${bytesToSize(size)})` : '';
|
|
47
|
+
return translate(
|
|
48
|
+
{
|
|
49
|
+
id: 'theme.IdealImageMessage.load',
|
|
50
|
+
message: 'Click to load{sizeMessage}',
|
|
51
|
+
description:
|
|
52
|
+
'To prompt users to load the full image. sizeMessage is a parenthesized size figure.',
|
|
53
|
+
},
|
|
54
|
+
{sizeMessage},
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
case 'offline':
|
|
58
|
+
return translate({
|
|
59
|
+
id: 'theme.IdealImageMessage.offline',
|
|
60
|
+
message: 'Your browser is offline. Image not loaded',
|
|
61
|
+
description: 'When the user is viewing an offline document',
|
|
62
|
+
});
|
|
63
|
+
case 'error': {
|
|
64
|
+
const {loadInfo} = state;
|
|
65
|
+
if (loadInfo === 404) {
|
|
66
|
+
return translate({
|
|
67
|
+
id: 'theme.IdealImageMessage.404error',
|
|
68
|
+
message: '404. Image not found',
|
|
69
|
+
description: 'When the image is not found',
|
|
70
|
+
});
|
|
71
|
+
} else {
|
|
72
|
+
return translate({
|
|
73
|
+
id: 'theme.IdealImageMessage.error',
|
|
74
|
+
message: 'Error. Click to reload',
|
|
75
|
+
description: 'When the image fails to load for unknown error',
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
default:
|
|
80
|
+
throw new Error(`Wrong icon: ${icon}`);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
13
84
|
function IdealImage(props: Props): JSX.Element {
|
|
14
85
|
const {alt, className, img} = props;
|
|
15
86
|
|
|
@@ -38,6 +109,7 @@ function IdealImage(props: Props): JSX.Element {
|
|
|
38
109
|
...image,
|
|
39
110
|
src: image.path,
|
|
40
111
|
}))}
|
|
112
|
+
getMessage={getMessage}
|
|
41
113
|
/>
|
|
42
114
|
);
|
|
43
115
|
}
|
package/tsconfig.browser.json
DELETED
package/tsconfig.json
DELETED
package/tsconfig.server.json
DELETED