📦 EqualifyEverything / equalify-schema

📄 axe-core.js · 132 lines
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
132function convertAxeResultsToEqualifySchema(axeResults) {
    let tagIdCounter = 1;
    let nodeIdCounter = 1;
    let ruleTagId, messageTagId;

    const nodeMap = new Map();
    const messageMap = new Map();
    const tagMap = new Map();

    const equalifySchemaData = {
        urls: [{ urlId: 1, url: axeResults.results.url }], // This script only converts one url
        messages: [],
        tags: [],
        nodes: []
    };

    const ensureTags = () => {
        if (!ruleTagId) {
            const ruleTag = 'axe-core Rule';
            ruleTagId = getOrCreateTagId(ruleTag);
        }
        if (!messageTagId) {
            const messageTag = 'axe-core Message';
            messageTagId = getOrCreateTagId(messageTag);
        }
    };

    const formatRuleId = (id) => id.replace(/-/g, ' ').split(' ').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');

    const getOrCreateTagId = (tag) => {
        if (tagMap.has(tag)) {
            return tagMap.get(tag);
        } else {
            const tagId = tagIdCounter++;
            tagMap.set(tag, tagId);
            equalifySchemaData.tags.push({ tagId, tag });
            return tagId;
        }
    };

    const getOrCreateNodeId = (html, targets) => {
        const key = `${html}::${targets.join(',')}`;
        if (!nodeMap.has(key)) {
            const nodeId = nodeIdCounter++;
            nodeMap.set(key, nodeId);
            equalifySchemaData.nodes.push({ 
                nodeId, 
                html, 
                targets, 
                relatedUrlId: 1,
                equalified: false  
             });
        }
        return nodeMap.get(key);
    };

    const addOrUpdateMessage = (messageText, messageType, isRule, html, targets, relatedHtmls, additionalTags = []) => {
        const nodeId = getOrCreateNodeId(html, targets);
        const key = `${messageText}::${messageType}`;
        const tagIds = [isRule ? ruleTagId : messageTagId].concat(
            additionalTags.map(tag => getOrCreateTagId(tag))
        );

        // Process related nodes
        const relatedNodeIds = relatedHtmls.map(relatedHtml => getOrCreateNodeId(relatedHtml, targets));

        if (!messageMap.has(key)) {
            const message = {
                message: messageText,
                relatedTagIds: tagIds,
                relatedNodeIds: [nodeId, ...relatedNodeIds],
                type: messageType
            };
            equalifySchemaData.messages.push(message);
            messageMap.set(key, message);
        } else {
            const existingMessage = messageMap.get(key);
            if (!existingMessage.relatedNodeIds.includes(nodeId)) {
                existingMessage.relatedNodeIds.push(nodeId);
            }
            relatedNodeIds.forEach(rNodeId => {
                if (!existingMessage.relatedNodeIds.includes(rNodeId)) {
                    existingMessage.relatedNodeIds.push(rNodeId);
                }
            });
        }
    };

    const processIssues = (issues, messageType) => {
        ensureTags();

        issues.forEach(issue => {
            const formattedRuleId = formatRuleId(issue.id);
            const ruleMessageText = `${formattedRuleId} Rule: ${issue.description}. ${issue.help}. More information: ${issue.helpUrl}`;

            issue.nodes.forEach(node => {
                const targets = node.target || [];
                const relatedHtmls = node.any.flatMap(detail => 
                    detail.relatedNodes ? detail.relatedNodes.map(rNode => rNode.html) : []
                );

                addOrUpdateMessage(ruleMessageText, messageType, true, node.html, targets, relatedHtmls, issue.tags);

                node.any.forEach(detail => {
                    const detailMessageText = detail.message;
                    addOrUpdateMessage(detailMessageText, messageType, false, node.html, targets, relatedHtmls, issue.tags);
                });

                const nodeId = getOrCreateNodeId(node.html, targets); 
                const nodeInEqualifySchema = equalifySchemaData.nodes.find(n => n.nodeId === nodeId);
                if (nodeInEqualifySchema) {
                    nodeInEqualifySchema.equalified = (messageType === 'pass');
                }
            });
        });
    };

    if (axeResults.results.violations) {
        processIssues(axeResults.results.violations, 'violation');
    }
    if (axeResults.results.incomplete) {
        processIssues(axeResults.results.incomplete, 'warning');
    }
    if (axeResults.results.passes) {
        processIssues(axeResults.results.passes, 'pass');
    }

    return equalifySchemaData;
}

module.exports = convertAxeResultsToEqualifySchema;