Skip to content

Commit e70c915

Browse files
authored
feat: add partial support for vscode protocol uri (#196)
1 parent 3f95821 commit e70c915

File tree

4 files changed

+73
-1
lines changed

4 files changed

+73
-1
lines changed

src/utils/schema.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,32 @@ function loadJsonInternal<T>(
4343
if (jsonPath.startsWith("http://") || jsonPath.startsWith("https://")) {
4444
return loadJsonFromURL(jsonPath, context, edit);
4545
}
46+
if (jsonPath.startsWith("vscode://")) {
47+
let url = `https://raw.githubusercontent.com/ota-meshi/extract-vscode-schemas/main/resources/vscode/${jsonPath.slice(
48+
9
49+
)}`;
50+
if (!url.endsWith(".json")) {
51+
url = `${url}.json`;
52+
}
53+
return loadJsonFromURL(url, context, (orig) => {
54+
const result = edit?.(orig) ?? orig;
55+
if (jsonPath === "vscode://schemas/settings/machine") {
56+
// Adjust `vscode://schemas/settings/machine` resource to avoid bugs.
57+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- ignore
58+
const target = (result as any)?.properties?.[
59+
"workbench.externalUriOpeners"
60+
]?.additionalProperties?.anyOf;
61+
removeEmptyEnum(target);
62+
} else if (jsonPath === "vscode://schemas/launch") {
63+
// Adjust `vscode://schemas/launch` resource to avoid bugs.
64+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- ignore
65+
const target = (result as any)?.properties?.compounds?.items?.properties
66+
?.configurations?.items?.oneOf;
67+
removeEmptyEnum(target);
68+
}
69+
return result;
70+
});
71+
}
4672
const json = fs.readFileSync(
4773
path.resolve(getCwd(context), jsonPath),
4874
"utf-8"
@@ -51,6 +77,33 @@ function loadJsonInternal<T>(
5177
return edit ? edit(data) : data;
5278
}
5379

80+
/** remove empty `enum:` schema */
81+
function removeEmptyEnum(
82+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- ignore
83+
target: any
84+
) {
85+
if (!target) return;
86+
if (Array.isArray(target)) {
87+
for (const e of target) {
88+
removeEmptyEnum(e);
89+
}
90+
return;
91+
}
92+
if (Array.isArray(target.enum) && target.enum.length === 0) {
93+
delete target.enum;
94+
return;
95+
}
96+
if (
97+
target.type === "object" &&
98+
target.properties &&
99+
typeof target.properties === "object"
100+
) {
101+
for (const key of Object.keys(target.properties)) {
102+
removeEmptyEnum(target.properties[key]);
103+
}
104+
}
105+
}
106+
54107
/**
55108
* Load schema data from url
56109
*/

src/utils/validator-factory.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ function resolveError(
114114
let schemaId = "";
115115
if (
116116
error.missingRef.startsWith("http://") ||
117-
error.missingRef.startsWith("https://")
117+
error.missingRef.startsWith("https://") ||
118+
error.missingRef.startsWith("vscode://")
118119
) {
119120
const uri = new URL(error.missingRef);
120121
uri.hash = "";
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"options": [
3+
{
4+
"schemas": [
5+
{
6+
"fileMatch": ["**/*.json"],
7+
"schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.schema.json"
8+
}
9+
]
10+
}
11+
]
12+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"name": "Node.js & TypeScript",
3+
"build": {
4+
"dockerfile": "Dockerfile"
5+
}
6+
}

0 commit comments

Comments
 (0)