Skip to content

Commit e15807b

Browse files
authored
Merge pull request #12 from Zosoled/legal-comments
Implement legal comment preservation option.
2 parents 45ef724 + b69ce5d commit e15807b

File tree

6 files changed

+111
-4
lines changed

6 files changed

+111
-4
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ build({
3333
|--------|-------------|---------|
3434
| minify | Enables or disables basic shader minification. | `false` |
3535
| resolveIncludes | When enabled, shaders can include other shaders with the custom `#include "path"` directive. | `true` |
36+
| legalComments | When enabled, preserves comments starting with `//!` or `/*!` and comments containing `@license` or `@preserve`. | `false` |
3637

3738
### TypeScript
3839

src/index.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ export interface GLSLOptions {
2525

2626
resolveIncludes?: boolean;
2727

28+
/**
29+
* Enables or disables shader legal comment preservation.
30+
* When enabled, comments starting with `//!` or `/*!`, or comments with the
31+
* text `@license` or `@preserve`, will be preserved.
32+
*
33+
* Default is `false`.
34+
*/
35+
36+
legalComments?: boolean;
37+
2838
}
2939

3040
/**
@@ -34,7 +44,7 @@ export interface GLSLOptions {
3444
* @return The plugin.
3545
*/
3646

37-
function glsl({ minify = false, resolveIncludes = true }: GLSLOptions = {}): Plugin {
47+
function glsl({ minify = false, resolveIncludes = true, legalComments = false }: GLSLOptions = {}): Plugin {
3848

3949
const cache = new Map<string, string>();
4050

@@ -47,7 +57,7 @@ function glsl({ minify = false, resolveIncludes = true }: GLSLOptions = {}): Plu
4757
const { contents, warnings, watchFiles } = await load(args.path, cache, resolveIncludes);
4858

4959
return {
50-
contents: minify ? minifyShader(contents as string) : contents,
60+
contents: minify ? minifyShader(contents as string, legalComments) : contents,
5161
warnings,
5262
watchFiles,
5363
loader: "text"

src/minifyShader.ts

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,26 @@
77
* @return The minified code.
88
*/
99

10-
export function minifyShader(source: string): string {
10+
export function minifyShader(source: string, legalComments: boolean): string {
1111

1212
const commentsRegExp = /[ \t]*(?:(?:\/\*[\s\S]*?\*\/)|(?:\/\/.*\n))/g;
1313
const symbolsRegExp = /\s*([{}=*,+/><&|[\]()\\!?:;-])\s*/g;
1414
const genericsRegExp = /(\w<\w+>)\s*(\w)/g;
15+
let preservedLegalComments: { comment: string; placeholder: string; }[] = [];
16+
17+
let result = source.replace(/\r/g, "");
18+
19+
// Preserve legal comments to be restored at the end, if requested
20+
if(legalComments) {
21+
22+
const preserved = preserveLegalComments(result);
23+
result = preserved.text;
24+
preservedLegalComments = preserved.comments;
25+
26+
}
27+
28+
result = result.replace(commentsRegExp, "");
1529

16-
let result = source.replace(/\r/g, "").replace(commentsRegExp, "");
1730
let separatedBySymbol = true;
1831
let wrap = false;
1932

@@ -59,6 +72,51 @@ export function minifyShader(source: string): string {
5972

6073
}, []).join("");
6174

75+
// Restore preserved legal comments, if requested
76+
if(legalComments) {
77+
78+
for(const legalComment of preservedLegalComments) {
79+
80+
result = result.replace(legalComment.placeholder, `\n${legalComment.comment}`);
81+
82+
}
83+
84+
}
85+
86+
6287
return result.replace(/\n{2,}/g, "\n");
6388

6489
}
90+
91+
// Finds legal comments and replaces them with placeholder text
92+
function preserveLegalComments(text: string) {
93+
94+
const legalComments = [];
95+
96+
// Get all statement-level comments
97+
const comments = text.matchAll(/^[ \t]*(?:(?:\/\/.*$)|(?:\/\*[\s\S]*?\*\/$))/gm);
98+
99+
let i = 0;
100+
101+
for(const comment of comments) {
102+
103+
if(/^[ \t]*\/[/*]!/gm.test(comment[0]) || comment[0].includes("@license") || comment[0].includes("@preserve")) {
104+
105+
const placeholder = `__LEGAL_COMMENT_${i}__`;
106+
legalComments.push({
107+
"comment": comment[0],
108+
placeholder
109+
});
110+
text = text.replace(comment[0], placeholder);
111+
i++;
112+
113+
}
114+
115+
}
116+
117+
return {
118+
text,
119+
comments: legalComments
120+
};
121+
122+
}

test/expected/wgsl-legal.min.js

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/src/shader.wgsl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,10 @@ fn fragmentMain(
5151
return vec4(surfaceColor, baseColor.a);
5252

5353
}
54+
55+
//! This is a single-line legal comment
56+
/*!
57+
* This is a multi-line legal comment.
58+
*/
59+
// @license This is a comment that specifies a license.
60+
// @preserve This is a comment that should be preserved.

test/test.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,27 @@ test("can use include", async(t) => {
9696
});
9797

9898
});
99+
100+
test("can preserve legal comments", async(t) => {
101+
102+
const config = {
103+
entryPoints: ["test/src/wgsl.ts"],
104+
outfile: "test/generated/wgsl-legal.min.js",
105+
platform: "node",
106+
format: "esm",
107+
bundle: true,
108+
minify: true,
109+
legalComments: "inline",
110+
plugins: [glsl({ minify: true, legalComments: true })]
111+
};
112+
113+
return build(config).then(async() => {
114+
115+
const actual = await readFile("test/generated/wgsl-legal.min.js", "utf8");
116+
const expected = await readFile("test/expected/wgsl-legal.min.js", "utf8");
117+
118+
t.is(actual.replace(EOL, ""), expected.replace(EOL, ""));
119+
120+
});
121+
122+
});

0 commit comments

Comments
 (0)