Newer
Older
import { useActions } from '../../../overmind';
Luciano Frizzera
committed
import { useAtomValue, useSetAtom } from 'jotai';
import { useTranslation } from 'react-i18next';
import { currentContentAtom, xmlValidityAtom } from '../store';
const {XMLValidator} = require('fast-xml-parser');
Luciano Frizzera
committed
export type XMLValidity =
| { valid: true }
| {
valid: false;
error: {
message: string;
positions?: {
line: number;
col: number;
}[];
};
};
export const useValidation = () => {
const { openDialog } = useActions().ui;
const { t } = useTranslation('leafwriter');
const currentContent = useAtomValue(currentContentAtom);
const setXmlValidity = useSetAtom(xmlValidityAtom);
const checkValidity = () => {
// Use fast-xml-parser to determine validty of XML document instead of canadian solution using DOM-Parser because
// the return values of DOMParser are not cross-browser compatible, the canadian way of interpreting them works only
// on chrom(e/ium)-based browser, we, however, test against Firefox first and foremost.
// One cavecat of using fast-xml-parser is, that the error message is not translated. However, persons directly editing XML
// should understand english well enough to at least understand the error message.
/*
Luciano Frizzera
committed
const parser = new DOMParser();
const doc = parser.parseFromString(currentContent, 'application/xml');
const errorNode = doc.querySelector('parsererror');
const errorString = errorNode?.querySelector('div')?.textContent;
if (!errorString) {
const validity: XMLValidity = { valid: true };
setXmlValidity(validity);
return validity;
}
const lines = [...errorString.matchAll(/line ([0-9]*)/g)];
const column = [...errorString.matchAll(/column ([0-9]*)/g)];
*/
const result = XMLValidator.validate(currentContent, {
allowBooleanAttributes: true
});
//console.log(result)
if (result === true) {
const validity: XMLValidity = { valid: true };
setXmlValidity(validity);
return validity;
}
Luciano Frizzera
committed
const positions = [{
line: result["err"]["line"],
col: result["err"]["col"],
}];
Luciano Frizzera
committed
const validity: XMLValidity = {
valid: false,
error: {
message: result["err"]["msg"],
Luciano Frizzera
committed
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
positions: positions,
},
};
setXmlValidity(validity);
return validity;
};
const handleValidationWarning = async (message: string): Promise<boolean> => {
return new Promise((resolve) => {
openDialog({
type: 'simple',
props: {
maxWidth: 'xs',
severity: 'warning',
title: t('leafwriter:xml_document_invalid'),
Body: () => message,
actions: [
{ action: 'cancel', label: t('leafwriter:commons.cancel') },
{
action: 'discard',
label: t('leafwriter:commons.discard_changes'),
variant: 'outlined',
},
],
onClose: async (action) => {
if (action === 'discard') return resolve(true);
return resolve(false);
},
},
});
});
};
return {
checkValidity,
handleValidationWarning,
};
};