mirror of
				https://scm.univ-tours.fr/22107988t/rappaurio-sae501_502.git
				synced 2025-11-04 06:05:22 +01: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;
 | 
						|
}
 |