Skip to content

Commit

Permalink
feat: improve errors
Browse files Browse the repository at this point in the history
  • Loading branch information
evilebottnawi committed Mar 18, 2020
1 parent 9923244 commit f2ce5b1
Show file tree
Hide file tree
Showing 9 changed files with 339 additions and 268 deletions.
56 changes: 56 additions & 0 deletions src/HtmlSourceError.js
@@ -0,0 +1,56 @@
function getIndices(value) {
const result = [];
let index = value.indexOf('\n');

while (index !== -1) {
result.push(index + 1);
index = value.indexOf('\n', index + 1);
}

result.push(value.length + 1);

return result;
}

function offsetToPosition(source, offset) {
let index = -1;
const indices = getIndices(source);
const { length } = indices;

if (offset < 0) {
return {};
}

// eslint-disable-next-line no-plusplus
while (++index < length) {
if (indices[index] > offset) {
return {
line: index + 1,
column: offset - (indices[index - 1] || 0) + 1,
offset,
};
}
}

return {};
}

export default class HtmlSourceError extends Error {
constructor(error, startIndex, endIndex, source) {
super(error);

this.name = 'HtmlSourceError';
this.message = `${this.name}: ${this.message}`;
this.startIndex = startIndex;
this.endIndex = endIndex;
this.source = source;

const startPosition = offsetToPosition(source, this.startIndex);
const endPosition = offsetToPosition(source, this.endIndex);

this.message += ` (From line ${startPosition.line}, column ${startPosition.column}; to line ${endPosition.line}, column ${endPosition.column})`;

// We don't need stack
this.stack = false;
}
}
16 changes: 0 additions & 16 deletions src/Warning.js

This file was deleted.

24 changes: 9 additions & 15 deletions src/index.js
Expand Up @@ -2,7 +2,6 @@ import { getOptions } from 'loader-utils';
import validateOptions from 'schema-utils';

import { sourcePlugin, minimizerPlugin } from './plugins';
import Warning from './Warning';

import {
pluginRunner,
Expand Down Expand Up @@ -40,37 +39,32 @@ export default function htmlLoader(content) {
plugins.push(minimizerPlugin({ minimize }));
}

const { html, messages, warnings, errors } = pluginRunner(plugins).process(
content
);

for (const warning of warnings) {
this.emitWarning(new Warning(warning));
}

for (const error of errors) {
this.emitError(new Error(error));
}
const { html, messages } = pluginRunner(plugins).process(content);

const errors = [];
const importedMessages = [];
const replaceableMessages = [];
const exportedMessages = [];

for (const message of messages) {
// eslint-disable-next-line default-case
switch (message.type) {
case 'error':
errors.push(message.value);
break;
case 'import':
importedMessages.push(message.value);
break;
case 'replacer':
replaceableMessages.push(message.value);
break;
case 'exports':
exportedMessages.push(message.value);
break;
}
}

for (const error of errors) {
this.emitError(error instanceof Error ? error : new Error(error));
}

const codeOptions = { ...options, loaderContext: this };
const importCode = getImportCode(html, importedMessages, codeOptions);
const moduleCode = getModuleCode(html, replaceableMessages, codeOptions);
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/minimizer-plugin.js
Expand Up @@ -23,7 +23,7 @@ export default (options) =>
// eslint-disable-next-line no-param-reassign
html = minify(html, minimizeOptions);
} catch (error) {
result.errors.push(error);
result.messages.push({ type: 'error', value: error });
}

return html;
Expand Down
37 changes: 23 additions & 14 deletions src/plugins/source-plugin.js
Expand Up @@ -3,6 +3,7 @@ import { parse } from 'url';
import { Parser } from 'htmlparser2';
import { isUrlRequest, urlToRequest } from 'loader-utils';

import HtmlSourceError from '../HtmlSourceError';
import { getFilter } from '../utils';

function isASCIIWhitespace(character) {
Expand Down Expand Up @@ -448,8 +449,6 @@ export default (options) =>
unquoted,
} = this.attributesMeta[attribute];

// TODO use code frame for errors

if (
!onOpenTagFilter.test(`:${attribute}`) &&
!onOpenTagFilter.test(`${tag}:${attribute}`)
Expand Down Expand Up @@ -478,11 +477,15 @@ export default (options) =>
try {
sourceSet = parseSrcset(value);
} catch (error) {
result.errors.push(
new Error(
`Bad value for attribute "${attribute}" on element "${tag}": ${error.message}`
)
);
result.messages.push({
type: 'error',
value: new HtmlSourceError(
`Bad value for attribute "${attribute}" on element "${tag}": ${error.message}`,
parser.startIndex,
parser.endIndex,
html
),
});

return;
}
Expand All @@ -507,11 +510,15 @@ export default (options) =>
try {
source = parseSrc(value);
} catch (error) {
result.errors.push(
new Error(
`Bad value for attribute "${attribute}" on element "${tag}": ${error.message}`
)
);
result.messages.push({
type: 'error',
value: new HtmlSourceError(
`Bad value for attribute "${attribute}" on element "${tag}": ${error.message}`,
parser.startIndex,
parser.endIndex,
html
),
});

return;
}
Expand All @@ -527,9 +534,11 @@ export default (options) =>

this.attributesMeta = {};
},
/* istanbul ignore next */
onerror(error) {
result.errors.push(error);
result.messages.push({
type: 'error',
value: error,
});
},
},
{
Expand Down
2 changes: 1 addition & 1 deletion src/utils.js
Expand Up @@ -5,7 +5,7 @@ const GET_SOURCE_FROM_IMPORT_NAME = '___HTML_LOADER_GET_SOURCE_FROM_IMPORT___';
export function pluginRunner(plugins) {
return {
process: (content) => {
const result = { messages: [], warnings: [], errors: [] };
const result = { messages: [] };

for (const plugin of plugins) {
// eslint-disable-next-line no-param-reassign
Expand Down

0 comments on commit f2ce5b1

Please sign in to comment.