Skip to content
This repository was archived by the owner on May 14, 2025. It is now read-only.

Commit e182364

Browse files
NiedziolkaMichalcaugnerqueengooborg
authored
feat(editor/js): convert to TypeScript (#1171)
Co-authored-by: Claas Augner <[email protected]> Co-authored-by: Queen Vinyl Da.i'gyu-Kazotetsu <[email protected]>
1 parent 02c183c commit e182364

23 files changed

+401
-331
lines changed

.eslintrc.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"sourceType": "module"
1919
},
2020
"rules": {
21-
"@typescript-eslint/no-explicit-any": "error",
21+
"@typescript-eslint/no-explicit-any": "off",
2222
"@typescript-eslint/no-unused-expressions": "error"
2323
},
2424
"settings": {

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,6 @@ typings/
6060

6161
# Built TypeScript files
6262
lib/*.js
63-
webpack.config.js
63+
lib/*.js.map
64+
editor/**/*.js
65+
editor/**/*.js.map

.prettierignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ node_modules
66
# This can be removed after https://github.com/googleapis/release-please/issues/1802 is fixed
77
CHANGELOG.md
88
# TSC output:
9-
webpack.config.js
109
lib/*.js
10+
editor/js/**/*.js

editor/js/editable-css.js renamed to editor/js/editable-css.ts

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,29 @@ import "../css/editor-libs/common.css";
1111
import "../css/editable-css.css";
1212

1313
(function () {
14-
const exampleChoiceList = document.getElementById("example-choice-list");
15-
const exampleChoices = exampleChoiceList.querySelectorAll(".example-choice");
14+
const exampleChoiceList = document.getElementById(
15+
"example-choice-list",
16+
) as HTMLElement;
17+
18+
const exampleChoices = exampleChoiceList.querySelectorAll(
19+
".example-choice",
20+
) as NodeListOf<HTMLElement>;
1621
const exampleDeclarations = Array.from(
1722
exampleChoices,
18-
(choice) => choice.querySelector("code").textContent,
23+
(choice) => choice.querySelector("code")?.textContent,
1924
);
20-
const editorWrapper = document.getElementById("editor-wrapper");
21-
const output = document.getElementById("output");
22-
const warningNoSupport = document.getElementById("warning-no-support");
23-
24-
const originalChoices = [];
25+
const editorWrapper = document.getElementById(
26+
"editor-wrapper",
27+
) as HTMLElement;
28+
const output = document.getElementById("output") as HTMLElement;
29+
const warningNoSupport = document.getElementById(
30+
"warning-no-support",
31+
) as HTMLElement;
32+
33+
const originalChoices: string[] = [];
2534
let initialChoice = 0;
2635

27-
function applyCodeMirror(target, code) {
36+
function applyCodeMirror(target: HTMLElement, code: string) {
2837
return initCodeEditor(target, code, languageCSS(), {
2938
lineNumbers: false,
3039
});
@@ -42,14 +51,16 @@ import "../css/editable-css.css";
4251
const exampleChoice = exampleChoices[i];
4352
const choiceButton = document.createElement("button");
4453
const choiceButtonText = document.createElement("span");
45-
const choiceCode = exampleChoice.querySelector("code");
46-
const copyButton = exampleChoice.getElementsByClassName("copy")[0];
54+
const choiceCode = exampleChoice.querySelector("code") as HTMLElement;
55+
const copyButton = exampleChoice.getElementsByClassName(
56+
"copy",
57+
)[0] as HTMLButtonElement;
4758

48-
originalChoices.push(choiceCode.textContent);
59+
originalChoices.push(choiceCode.textContent || "");
4960

5061
const codeMirrorEditor = applyCodeMirror(
51-
exampleChoice.querySelector("pre"),
52-
choiceCode.textContent,
62+
exampleChoice.querySelector("pre") as HTMLElement,
63+
choiceCode.textContent || "",
5364
);
5465

5566
choiceButton.setAttribute("type", "button");
@@ -82,11 +93,12 @@ import "../css/editable-css.css";
8293
* reset all the CSS examples to their original state
8394
*/
8495
function handleResetEvents() {
85-
const resetButton = document.getElementById("reset");
96+
const resetButton = document.getElementById("reset") as HTMLElement;
8697

8798
resetButton.addEventListener("click", () => {
8899
exampleChoices.forEach((e, i) => {
89-
const preEl = e.querySelector("pre");
100+
const preEl = e.querySelector("pre") as HTMLElement;
101+
90102
// Remove original codemirror
91103
for (const e of preEl.children) {
92104
e.remove();
@@ -100,16 +112,16 @@ import "../css/editable-css.css";
100112

101113
// if there is an initial choice set, set it as selected
102114
if (initialChoice) {
103-
mceEvents.onChoose(exampleChoices[initialChoice]);
104-
clippy.toggleClippy(exampleChoices[initialChoice]);
115+
mceEvents.onChoose(exampleChoices[initialChoice] as HTMLElement);
116+
clippy.toggleClippy(exampleChoices[initialChoice] as HTMLElement);
105117
} else {
106-
mceEvents.onChoose(exampleChoices[0]);
107-
clippy.toggleClippy(exampleChoices[0]);
118+
mceEvents.onChoose(exampleChoices[0] as HTMLElement);
119+
clippy.toggleClippy(exampleChoices[0] as HTMLElement);
108120
}
109121
});
110122
}
111123

112-
function indexOf(exampleChoices, choice) {
124+
function indexOf(exampleChoices: NodeListOf<Element>, choice: Element) {
113125
for (let i = 0, l = exampleChoices.length; i < l; i++) {
114126
if (exampleChoices[i] === choice) {
115127
return i;
@@ -126,23 +138,24 @@ import "../css/editable-css.css";
126138
function handleChoiceHover() {
127139
for (let i = 0, l = exampleChoices.length; i < l; i++) {
128140
const choice = exampleChoices[i];
129-
const copyBtn = choice.querySelector(".copy");
141+
const copyBtn = choice.querySelector(".copy") as HTMLElement;
142+
130143
copyBtn.setAttribute("aria-label", "Copy to clipboard");
131144

132145
choice.addEventListener("mouseover", () => {
133-
copyBtn.setAttribute("aria-hidden", false);
146+
copyBtn.setAttribute("aria-hidden", "false");
134147
});
135148
choice.addEventListener("mouseout", () => {
136-
copyBtn.setAttribute("aria-hidden", true);
149+
copyBtn.setAttribute("aria-hidden", "true");
137150
});
138151
}
139152
}
140153

141154
/* only show the live code view if JS is enabled and the property is supported. */
142155
if (cssEditorUtils.isAnyDeclarationSetSupported(exampleDeclarations)) {
143156
enableLiveEditor();
144-
mceEvents.onChoose(exampleChoices[initialChoice]);
145-
clippy.toggleClippy(exampleChoices[initialChoice]);
157+
mceEvents.onChoose(exampleChoices[initialChoice] as HTMLElement);
158+
clippy.toggleClippy(exampleChoices[initialChoice] as HTMLElement);
146159
} else {
147160
warningNoSupport.classList.remove("hidden");
148161
}

editor/js/editable-js.js renamed to editor/js/editable-js.ts

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { EditorView } from "codemirror";
12
import * as featureDetector from "./editor-libs/feature-detector.js";
23
import mceConsole from "./editor-libs/console.js";
34
import * as mceEvents from "./editor-libs/events.js";
@@ -12,35 +13,40 @@ import {
1213
} from "./editor-libs/codemirror-editor.js";
1314

1415
(function () {
15-
const codeBlock = document.getElementById("static-js");
16+
const codeBlock = document.getElementById("static-js") as HTMLElement;
17+
1618
const exampleFeature = codeBlock.dataset["feature"];
17-
const execute = document.getElementById("execute");
18-
const output = document.querySelector("#console code");
19-
const reset = document.getElementById("reset");
19+
const execute = document.getElementById("execute") as HTMLElement;
20+
const output = document.querySelector("#console code") as HTMLElement;
21+
const reset = document.getElementById("reset") as HTMLElement;
2022

21-
let codeMirror;
23+
let codeMirror: EditorView | null;
2224
let staticContainer;
23-
let liveContainer = "";
25+
let liveContainer;
2426

2527
/**
2628
* Reads the textContent from the interactiveCodeBlock, sends the
2729
* textContent to executeLiveExample, and logs the output to the
2830
* output container
2931
*/
3032
function applyCode() {
31-
const currentValue = getEditorContent(codeMirror);
33+
if (!codeMirror) {
34+
initCodeMirror();
35+
// "as EditorView" on next line needed to trick TypeScript
36+
}
37+
const currentValue = getEditorContent(codeMirror as EditorView);
3238
updateOutput(currentValue);
3339
}
3440

3541
/**
3642
* Initialize CodeMirror
3743
*/
3844
function initCodeMirror() {
39-
const editorContainer = document.getElementById("editor");
45+
const editorContainer = document.getElementById("editor") as HTMLElement;
4046

4147
codeMirror = initCodeEditor(
4248
editorContainer,
43-
codeBlock.textContent,
49+
codeBlock.textContent || "",
4450
languageJavaScript(),
4551
);
4652
}
@@ -51,15 +57,15 @@ import {
5157
function initInteractiveEditor() {
5258
/* If the `data-height` attribute is defined on the `codeBlock`, set
5359
the value of this attribute as a class on the editor element. */
54-
if (codeBlock.dataset["height"]) {
55-
const editor = document.getElementById("editor");
60+
if (codeBlock?.dataset["height"]) {
61+
const editor = document.getElementById("editor") as HTMLElement;
5662
editor.classList.add(codeBlock.dataset["height"]);
5763
}
5864

59-
staticContainer = document.getElementById("static");
65+
staticContainer = document.getElementById("static") as HTMLElement;
6066
staticContainer.classList.add("hidden");
6167

62-
liveContainer = document.getElementById("live");
68+
liveContainer = document.getElementById("live") as HTMLElement;
6369
liveContainer.classList.remove("hidden");
6470

6571
mceConsole();
@@ -73,21 +79,22 @@ import {
7379
* to the output container.
7480
* @param {String} exampleCode - The code to execute
7581
*/
76-
function updateOutput(exampleCode) {
82+
function updateOutput(exampleCode: string) {
7783
output.classList.add("fade-in");
7884

7985
try {
8086
// Create a new Function from the code, and immediately execute it.
8187
new Function(exampleCode)();
82-
} catch (event) {
83-
output.textContent = "Error: " + event.message;
88+
} catch (event: unknown) {
89+
output.textContent = "Error: " + (event as Error)?.message;
8490
}
8591

8692
output.addEventListener("animationend", () =>
8793
output.classList.remove("fade-in"),
8894
);
8995
}
9096

97+
/* only execute code in supported browsers */
9198
if (featureDetector.isDefined(exampleFeature)) {
9299
document.documentElement.classList.add("js");
93100

@@ -99,5 +106,9 @@ import {
99106
});
100107

101108
reset.addEventListener("click", () => window.location.reload());
109+
} else {
110+
console.warn(
111+
`Feature ${exampleFeature} is not supported; code editor disabled.`,
112+
);
102113
}
103114
})();

0 commit comments

Comments
 (0)