mirror of
https://scm.univ-tours.fr/22107988t/rappaurio-sae501_502.git
synced 2025-08-30 15:45:58 +02:00
150 lines
4.7 KiB
JavaScript
150 lines
4.7 KiB
JavaScript
import fetch from 'cross-fetch';
|
|
import querystring from 'querystring';
|
|
const fetchOptions = {
|
|
method: 'GET',
|
|
mode: 'cors',
|
|
credentials: 'omit'
|
|
};
|
|
export function api(apiOptions, params = {}) {
|
|
const qs = Object.assign({
|
|
format: 'json',
|
|
action: 'query',
|
|
redirects: '1'
|
|
}, params);
|
|
// Remove undefined properties
|
|
Object.keys(qs).forEach(key => {
|
|
if (qs[key] === undefined) {
|
|
delete qs[key];
|
|
}
|
|
});
|
|
if (apiOptions.origin) {
|
|
qs.origin = apiOptions.origin;
|
|
}
|
|
const url = `${apiOptions.apiUrl}?${querystring.stringify(qs)}`;
|
|
const headers = Object.assign({ 'User-Agent': 'WikiJS Bot v1.0' }, apiOptions.headers);
|
|
return fetch(url, Object.assign({ headers }, fetchOptions))
|
|
.then(res => {
|
|
if (res.ok) {
|
|
return res.json();
|
|
}
|
|
throw new Error(`${res.status}: ${res.statusText}`);
|
|
})
|
|
.then(res => {
|
|
if (res.error) {
|
|
throw new Error(res.error.info);
|
|
}
|
|
return res;
|
|
});
|
|
}
|
|
export function pagination(apiOptions, params, parseResults) {
|
|
return api(apiOptions, params).then(res => {
|
|
let resolution = {};
|
|
resolution.results = parseResults(res);
|
|
resolution.query = params.srsearch;
|
|
if (res['continue']) {
|
|
const continueType = Object.keys(res['continue']).filter(key => key !== 'continue')[0];
|
|
const continueKey = res['continue'][continueType];
|
|
params[continueType] = continueKey;
|
|
resolution.next = () => pagination(apiOptions, params, parseResults);
|
|
}
|
|
return resolution;
|
|
});
|
|
}
|
|
export function aggregatePagination(pagination, previousResults = []) {
|
|
return pagination.then(res => {
|
|
const results = [...previousResults, ...res.results];
|
|
if (res.next) {
|
|
return aggregatePagination(res.next(), results);
|
|
}
|
|
else {
|
|
return results;
|
|
}
|
|
});
|
|
}
|
|
const pageLimit = 500;
|
|
export function aggregate(apiOptions, params, list, key, prefix, results = []) {
|
|
params.list = list;
|
|
params[prefix + 'limit'] = pageLimit;
|
|
return api(apiOptions, params).then(res => {
|
|
const nextResults = [...results, ...res.query[list].map(e => e[key])];
|
|
const continueWith = res['query-continue'] || res.continue;
|
|
if (continueWith) {
|
|
const nextFromKey = (continueWith[list] && continueWith[list][prefix + 'from']) ||
|
|
(continueWith[list] && continueWith[list][prefix + 'continue']) ||
|
|
continueWith[prefix + 'continue'];
|
|
params[prefix + 'continue'] = nextFromKey;
|
|
params[prefix + 'from'] = nextFromKey;
|
|
return aggregate(apiOptions, params, list, key, prefix, nextResults);
|
|
}
|
|
return nextResults;
|
|
});
|
|
}
|
|
const headingPattern = /(==+)(?:(?!\n)\s?)((?:(?!==|\n)[^])+)(?:(?!\n)\s?)(==+)/g;
|
|
function getHeadings(text) {
|
|
let match;
|
|
const matches = [];
|
|
while ((match = headingPattern.exec(text)) !== null) {
|
|
matches.push({
|
|
level: match[1].trim().length,
|
|
text: match[2].trim(),
|
|
start: match.index,
|
|
end: match.index + match[0].length
|
|
});
|
|
}
|
|
return matches;
|
|
}
|
|
export function parseContent(source) {
|
|
const headings = getHeadings(source);
|
|
const minLevel = Math.min(...headings.map(({ level }) => level));
|
|
const sections = headings.map((heading, index) => {
|
|
const next = headings[index + 1];
|
|
const content = source
|
|
.substring(heading.end, next ? next.start : undefined)
|
|
.trim();
|
|
return {
|
|
title: heading.text,
|
|
level: heading.level - minLevel,
|
|
id: index,
|
|
content,
|
|
items: []
|
|
};
|
|
});
|
|
const lastParentLevel = (index, level) => {
|
|
if (level === 0)
|
|
return null;
|
|
for (let i = index - 1; i >= 0; i--) {
|
|
if (sections[i].level < level) {
|
|
return sections[i].id;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
// Set parents
|
|
sections.forEach((section, index) => {
|
|
section.parent = lastParentLevel(index, section.level);
|
|
});
|
|
const root = {
|
|
items: []
|
|
};
|
|
const findSection = id => sections.find(s => id === s.id);
|
|
// Organize
|
|
sections.forEach(section => {
|
|
if (section.parent === null) {
|
|
root.items.push(section);
|
|
}
|
|
else {
|
|
findSection(section.parent).items.push(section);
|
|
}
|
|
});
|
|
// Clean up
|
|
sections.forEach(section => {
|
|
delete section.id;
|
|
delete section.parent;
|
|
delete section.level;
|
|
if (!section.items.length) {
|
|
delete section.items;
|
|
}
|
|
});
|
|
return root.items;
|
|
}
|