• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nightlycommit / rollup-plugin-twig / 47

17 Jun 2025 11:22AM UTC coverage: 100.0%. Remained the same
47

push

gitlab-ci

Eric MORAND
Merge branch 'issue-11' into 'main'

Resolve issue #11

Closes #11

See merge request nightlycommit/rollup-plugin-twig!8

20 of 20 branches covered (100.0%)

Branch coverage included in aggregate %.

49 of 49 relevant lines covered (100.0%)

28.04 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

100.0
/src/lib/plugin.ts
1
import type {Plugin} from "rollup";
2
import type {FilterPattern} from "@rollup/pluginutils";
3
import {createFilter} from "@rollup/pluginutils";
4
import {extname} from "path";
5
import {
6
    createSource,
7
    type TwingEnvironment,
8
    type TwingSynchronousEnvironment,
9
    type TwingParsingError
10
} from "twing";
11
import {visit} from "./visitor";
12
import type {TransformResult} from "rollup";
13

14
export type PluginFactory = (environment: TwingEnvironment | TwingSynchronousEnvironment, options?: {
15
    include?: FilterPattern,
16
    exclude?: FilterPattern,
17
    emitSynchronousTemplates?: boolean;
18
}) => Plugin;
19

20
const createTwigPlugin: PluginFactory = (environment, options) => {
1✔
21
    const filter = createFilter(options?.include, options?.exclude);
16✔
22
    const extensions = ['.twig'];
16✔
23

24
    const plugin: Plugin = {
16✔
25
        name: 'twig',
26
        transform(
27
            this,
28
            code,
29
            id
30
        ) {
31
            if (!filter(id) || !extensions.includes(extname(id))) {
58✔
32
                return;
1✔
33
            }
34

35
            try {
36
                const ast = environment.parse(environment.tokenize(createSource(id, code)));
28✔
37

38
                return visit(ast, environment, id)
27✔
39
                    .then<TransformResult>((encounteredTemplates) => {
40
                        let index = 0;
27✔
41

42
                        const dependencies = encounteredTemplates.map(([templateName, resolvedName]) => {
27✔
43
                            return `import template${index} from "${resolvedName}";
13✔
44
templates.set('${templateName}', template${index++});`;
45
                        }).join('');
46

47
                        let generatedCode: string;
48

49
                        if (options?.emitSynchronousTemplates === true) {
81✔
50
                            generatedCode = `import {createSynchronousTemplate} from "twing";
1✔
51

52
const templates = new Map();
53

54
${dependencies}
55

56
const template = createSynchronousTemplate(${JSON.stringify(ast)});
57
const baseLoadTemplate = template.loadTemplate;
58

59
template.loadTemplate = (executionContext, identifier) => {
60
    return templates.has(identifier) ? templates.get(identifier) : baseLoadTemplate(executionContext, identifier);
61
};
62

63
for (const [, embeddedTemplate] of template.embeddedTemplates) {
64
    embeddedTemplate.loadTemplate = template.loadTemplate;
65
}
66

67
export default template;`;
68
                        }
69
                        else {
70
                            generatedCode = `import {createTemplate} from "twing";
26✔
71

72
const templates = new Map();
73

74
${dependencies}
75

76
const template = createTemplate(${JSON.stringify(ast)});
77
const baseLoadTemplate = template.loadTemplate;
78

79
template.loadTemplate = (executionContext, identifier) => {
80
    return templates.has(identifier) ? Promise.resolve(templates.get(identifier)) : baseLoadTemplate(executionContext, identifier);
81
};
82

83
for (const [, embeddedTemplate] of template.embeddedTemplates) {
84
    embeddedTemplate.loadTemplate = template.loadTemplate;
85
}
86

87
export default template;`;
88
                        }
89

90
                        return {
27✔
91
                            code: generatedCode,
92
                            map: {
93
                                mappings: ''
94
                            }
95
                        };
96
                    });
97
            } catch (error) {
98
                const {message, location} = (error as TwingParsingError);
1✔
99
                const {line, column} = location!;
1✔
100

101
                return this.error(new Error(message), {
1✔
102
                    line,
103
                    column: column - 1
104
                });
105
            }
106
        }
107
    };
108

109
    return plugin;
16✔
110
};
111

112
export default createTwigPlugin;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc