forked from javascript-tutorial/server
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathloadImgSizeAsync.js
More file actions
executable file
·139 lines (97 loc) · 3.17 KB
/
loadImgSizeAsync.js
File metadata and controls
executable file
·139 lines (97 loc) · 3.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
'use strict';
const assert = require('assert');
assert(typeof IS_CLIENT === 'undefined');
const imageSize = require('image-size');
const path = require('path');
const tokenUtils = require('./utils/token');
const t = require('i18n');
const fs = require('mz/fs');
const gm = require('gm');
t.requirePhrase('markit', 'error');
class SrcError extends Error {
}
module.exports = async function(tokens, options) {
for (let idx = 0; idx < tokens.length; idx++) {
let token = tokens[idx];
if (token.type == 'figure') {
await processImageOrFigure(token);
continue;
}
if (token.type != 'inline') continue;
for (let i = 0; i < token.children.length; i++) {
let inlineToken = token.children[i];
// <td><figure></td> gives figure inside inline token
if (inlineToken.type != 'image' && inlineToken.type != 'figure') continue;
await processImageOrFigure(inlineToken);
}
}
async function processImageOrFigure(token) {
if (token.attrIndex('height') != -1 || token.attrIndex('width') != -1) return;
try {
await doProcessImageOrFigure(token);
} catch (error) {
if (error instanceof SrcError) {
// replace image with error text
token.type = (token.type == 'image') ? 'markdown_error_inline' : 'markdown_error_block';
token.tag = '';
token.children = null;
token.attrs = null;
token.content = error.message;
} else {
throw error;
}
}
}
function srcUnderRoot(root, src) {
let absolutePath = path.join(root, src);
if (absolutePath.slice(0, root.length + 1) != root + path.sep) {
throw new SrcError(t('markit.error.src_out_of_root', {src}));
}
return absolutePath;
}
async function getImageInfo(src) {
let sourcePath = srcUnderRoot(
options.publicRoot,
src
);
// check readability
let stat;
try {
stat = await fs.stat(sourcePath);
} catch (e) {
throw new SrcError(t('markit.error.image_not_found', {src}));
}
if (!stat.isFile()) {
throw new SrcError(t('markit.error.image_not_found', {src}));
}
if (/\.svg$/i.test(sourcePath)) {
try {
let size = await function(callback) {
// GraphicsMagick fails with `gm identify my.svg`
gm(sourcePath).options({imageMagick: true}).identify('{"width":%w,"height":%h}', callback);
};
size = JSON.parse(size); // warning: no error processing
return size;
} catch (e) {
throw new SrcError(`${src}: ${e.message}`);
}
}
try {
return await new Promise((resolve, reject) => {
imageSize(sourcePath, (err, res) => err ? reject(err) : resolve(res));
});
} catch (e) {
if (e instanceof TypeError) {
throw new SrcError(t('markit.error.image_invalid', {src}));
}
throw new SrcError(`${src}: ${e.message}`);
}
}
async function doProcessImageOrFigure(token) {
let src = tokenUtils.attrGet(token, 'src');
if (!src) return;
let imageInfo = await getImageInfo(src);
tokenUtils.attrReplace(token, 'width', imageInfo.width);
tokenUtils.attrReplace(token, 'height', imageInfo.height);
}
};