├── .gitignore
├── .npmignore
├── README.md
├── index.mjs
├── package.json
├── rollup.config.mjs
└── test
├── basic.js
├── decoding.js
├── dummy-200x200.png
└── image-size.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | index.js
3 | package-lock.json
4 |
5 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | test/
3 | .gitignore
4 | package-lock.json
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | A markdown-it plugin supporting Chrome 75's [native image lazy-loading](https://addyosmani.com/blog/lazy-loading/) and [async decoding](https://github.com/whatwg/html/pull/3221).
2 |
3 | ## Install
4 |
5 | ```bash
6 | $ npm install markdown-it-image-lazy-loading
7 | ```
8 |
9 | ## Usage
10 |
11 | Load it in ES module.
12 |
13 | ```javascript
14 | import markdownit from 'markdown-it';
15 | import lazy_loading from 'markdown-it-image-lazy-loading';
16 |
17 | const md = markdownit();
18 | md.use(lazy_loading);
19 | md.render(``);
20 | //

\n
21 | ```
22 |
23 | Or load it in CommonJS module.
24 |
25 | ```javascript
26 | const md = require('markdown-it')();
27 | const lazy_loading = require('markdown-it-image-lazy-loading');
28 | md.use(lazy_loading);
29 |
30 | md.render(``);
31 | // 
\n
32 | ```
33 |
34 | If you want the `decoding="async"` attribute, enable the plugin's `decoding` option.
35 |
36 | ```javascript
37 | md.use(lazy_loading, {
38 | decoding: true,
39 | });
40 |
41 | md.render(``);
42 | // 
\n
43 | ```
44 |
45 | The plugin can also add `width` and `height` attributes to each image. This can prevent [cumulative layout shifts (CLS)](https://web.dev/cls/):
46 |
47 | ```javascript
48 | md.use(lazy_loading, {
49 | image_size: true,
50 |
51 | // Where your images are stored
52 | base_path: __dirname + 'src/',
53 | });
54 |
55 | md.render(``);
56 | // 
\n
57 | ```
58 |
59 | To keep images responsive, also include the following CSS:
60 | ```css
61 | img{
62 | max-width: 100%;
63 | height: auto;
64 | }
65 | ```
66 |
67 | ## License
68 |
69 | MIT
70 |
--------------------------------------------------------------------------------
/index.mjs:
--------------------------------------------------------------------------------
1 | import imageSize from 'image-size';
2 | import path from 'node:path';
3 |
4 | function lazy_loading_plugin(md, mdOptions) {
5 | var defaultImageRenderer = md.renderer.rules.image;
6 |
7 | md.renderer.rules.image = function (tokens, idx, options, env, self) {
8 | var token = tokens[idx];
9 | token.attrSet('loading', 'lazy');
10 |
11 | if (mdOptions && mdOptions.decoding === true) {
12 | token.attrSet('decoding', 'async');
13 | }
14 |
15 | if (mdOptions && mdOptions.base_path && mdOptions.image_size === true) {
16 | const imgSrc = token.attrGet('src');
17 | const imgPath = path.join(mdOptions.base_path, imgSrc);
18 | const dimensions = imageSize(imgPath);
19 |
20 | token.attrSet('width', dimensions.width);
21 | token.attrSet('height', dimensions.height);
22 | }
23 |
24 | return defaultImageRenderer(tokens, idx, options, env, self);
25 | };
26 | };
27 |
28 | export default lazy_loading_plugin;
29 |
30 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "markdown-it-image-lazy-loading",
3 | "version": "2.0.1",
4 | "description": "a markdown-it plugin supporting Chrome 75's native image lazy-loading",
5 | "main": "index.js",
6 | "exports": {
7 | ".": {
8 | "import": "./index.mjs",
9 | "require": "./index.js"
10 | }
11 | },
12 | "scripts": {
13 | "build": "rollup --config rollup.config.mjs",
14 | "test": "npm run build && npx tape test/*.js",
15 | "prepublishOnly": "npm run build"
16 | },
17 | "keywords": [
18 | "markdown-it-plugin",
19 | "markdown-it",
20 | "lazyload"
21 | ],
22 | "author": "Ruan Yifeng ",
23 | "homepage": "https://github.com/ruanyf/markdown-it-image-lazy-loading",
24 | "repository": "https://github.com/ruanyf/markdown-it-image-lazy-loading.git",
25 | "license": "MIT",
26 | "dependencies": {
27 | "image-size": "^1.0.0"
28 | },
29 | "devDependencies": {
30 | "markdown-it": "^14.0.0",
31 | "rollup": "^4.9.1",
32 | "tape": "^5.3.2"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/rollup.config.mjs:
--------------------------------------------------------------------------------
1 | export default {
2 | input: 'index.mjs',
3 | output: {
4 | file: 'index.js',
5 | format: 'cjs'
6 | },
7 | external: ['image-size', 'node:path']
8 | };
9 |
--------------------------------------------------------------------------------
/test/basic.js:
--------------------------------------------------------------------------------
1 | var test = require('tape');
2 |
3 | var md = require('markdown-it')();
4 | var lazy_loading = require('../index.js');
5 | md.use(lazy_loading);
6 |
7 | test('lazy loading test', function (t) {
8 | t.plan(1);
9 |
10 | t.equal(
11 | md.render(``),
12 | '
\n'
13 | );
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/decoding.js:
--------------------------------------------------------------------------------
1 | var test = require('tape');
2 |
3 | var md = require('markdown-it')();
4 | var lazy_loading = require('../index.js');
5 | md.use(lazy_loading, {
6 | decoding: true,
7 | });
8 |
9 | test('decoding test', function (t) {
10 | t.plan(1);
11 |
12 | t.equal(
13 | md.render(``),
14 | '
\n'
15 | );
16 |
17 | });
18 |
19 |
--------------------------------------------------------------------------------
/test/dummy-200x200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruanyf/markdown-it-image-lazy-loading/4d4ce4ba27fe5ebed16cb72a719803a6382154d8/test/dummy-200x200.png
--------------------------------------------------------------------------------
/test/image-size.js:
--------------------------------------------------------------------------------
1 | var test = require('tape');
2 |
3 | var md = require('markdown-it')();
4 | var lazy_loading = require('../index.js');
5 | md.use(lazy_loading, {
6 | image_size: true,
7 | base_path: __dirname,
8 | });
9 |
10 | test('image size test', function (t) {
11 | t.plan(1);
12 |
13 | t.equal(
14 | md.render(``),
15 | '
\n'
16 | );
17 |
18 | });
19 |
20 |
--------------------------------------------------------------------------------