Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion code-input.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ export class CodeInput extends HTMLTextAreaElement { // Tries to implement texta
/**
* When the code-input's template is registered, this contains its codeInput.Template object.
*/
templateObject?: readonly Template
/*readonly*/ templateObject?: Template // `readonly` commented for backwards compatibility
/**
* Exposed child textarea element for user to input code in; in this version of code-input you shouldn't need to access
* it because most textarea functionality is present on the code-input element itself.
Expand Down
2 changes: 1 addition & 1 deletion esm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ If you are using Yarn, NPM, or a similar package manager, the files should have
Otherwise, after changing directory to the one containing this file:

- If you have Node.js installed, run `node generate.mjs`.
- If you don't have Node.js installed but are on a POSIX-like system with `bash`/`zsh`, run `sh ./generate.sh`.
- If you don't have Node.js installed but are on a POSIX-like system with `bash`/`zsh`, run `sh ./generate.sh`. (This uses features like `grep -o`, so won't work on *absolutely all* POSIX systems. It works on many computers though, so try it out first!) **Security-wise, we don't prevent JavaScript**
- If neither of the above are true, install Node.js or (slightly harder; look online) a POSIX/"Linux" compatible shell.

## Extra Information
Expand Down
64 changes: 53 additions & 11 deletions esm/generate.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,30 @@ const AUTOGENERATED_NOTICE = "// NOTICE: This code is @generated from code outsi
copyingCode = true; // After is code to copy - this line missed out
}
}
await codeInputDMts.writeFile("export default { Plugin, Template, CodeInput, registerTemplate };\n");
await codeInputDMts.writeFile(`

// Prepare the default export:

// Values under the default export
declare const _default: {
Plugin: typeof Plugin;
Template: typeof Template;
CodeInput: typeof CodeInput;
registerTemplate: typeof registerTemplate;
}

// Type aliases to prevent ambiguous 'Plugin = Plugin'
declare type _Plugin = Plugin;
declare type _Template = Template;
declare type _CodeInput = CodeInput;
// Types under the default export
declare namespace _default {
export type Plugin = _Plugin;
export type Template = _Template;
export type CodeInput = _CodeInput;
}

export default _default;`);

await codeInputDTs.close();
await codeInputDMts.close();
Expand Down Expand Up @@ -127,7 +150,7 @@ const AUTOGENERATED_NOTICE = "// NOTICE: This code is @generated from code outsi
const templateDMts = await open("templates/"+templateName+".d.mts", "w")
await templateDMts.writeFile(AUTOGENERATED_NOTICE);
// Imports
await templateDMts.writeFile("import { Template, Plugin } from \"../code-input.d.mts\";\n");
await templateDMts.writeFile("import type { Template, Plugin } from \"../code-input.d.mts\";\n");
// Code after start and before end of this template, making use of the imported Template, not codeInput.Template
let copyingCode = false;
let classSeen = false;
Expand Down Expand Up @@ -185,7 +208,7 @@ const AUTOGENERATED_NOTICE = "// NOTICE: This code is @generated from code outsi
// Imports
await pluginMjs.writeFile("import { Plugin } from \"../code-input.mjs\";\n")
// Plugin syntax is to be stored in an object; do so temporarily.
await pluginMjs.writeFile("const plugins = {};\n");
await pluginMjs.writeFile("let plugins = {};\n");
// Code from this plugin"s file, making use of the imported Plugin, not codeInput.Plugin, and of the created plugins object, not codeInput.plugins
let pluginClassName = null;
for await (const line of pluginJs.readLines()) {
Expand Down Expand Up @@ -213,26 +236,45 @@ const AUTOGENERATED_NOTICE = "// NOTICE: This code is @generated from code outsi
const pluginDMts = await open("plugins/"+pluginName+".d.mts", "w")
await pluginDMts.writeFile(AUTOGENERATED_NOTICE);
// Imports
await pluginDMts.writeFile("import { Plugin, CodeInput } from \"../code-input.d.mts\";\n");
// Code after start and before end of this plugin, making use of the imported Template, not codeInput.Template
await pluginDMts.writeFile("import type { Plugin, CodeInput } from \"../code-input.d.mts\";\n");

// 1. Get the name of the Plugin class
let copyingCode = false;
let functionSeen = false;
let className = null;
const lines = [];
for await (let line of codeInputDTs.readLines()) {
if(line.includes("ESM-SUPPORT-END-PLUGIN-"+pluginName)) {
break;
}
if(copyingCode) {
if(/( |\t)*class.*/.test(line) && !functionSeen) {
// Replace only first occurrence
line = line.replace("class", "export default class");
functionSeen = true;
lines.push(line);
if(className === null) {
const classRegExpMatch = line.match(/^ *class ([A-Za-z]+)/);
if(classRegExpMatch !== null) {
// Replace only first occurrence
className = classRegExpMatch[1];
}
}
await pluginDMts.writeFile(line.replaceAll("codeInput.Plugin", "Plugin").replaceAll("codeInput.CodeInput", "CodeInput")+"\n");
}
if(line.includes("ESM-SUPPORT-START-PLUGIN-"+pluginName)) {
copyingCode = true; // After is code to copy - this line missed out
}
}
if(className === null) throw new Error(`ESM-SUPPORT-START-PLUGIN-${pluginName} section of code-input.d.ts does not contain a line matching /^ *class ([A-Za-z]+)/, but it should!`);

// 2. Edit the lines
for await (let line of lines) {
if(copyingCode) {
await pluginDMts.writeFile(line
.replaceAll("codeInput.Plugin", "Plugin")
.replaceAll("codeInput.CodeInput", "CodeInput")
.replaceAll(`class ${className}`, `declare class ${className}`)
.replaceAll(`namespace ${className}`, `declare namespace ${className}`)
.replaceAll(`codeInput.plugins.${className}`, className)
+"\n");
}
}
await pluginDMts.writeFile(`export default ${className};\n`);
await codeInputDTs.close();
await pluginDMts.close();
}
Expand Down
68 changes: 53 additions & 15 deletions esm/generate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ AUTOGENERATED_NOTICE="// NOTICE: This code is @generated from code outside the e
echo "" >> code-input.mjs
# Imports: Nothing
# Code before first templates block
head -$(($(sed -n "/ESM-SUPPORT-START-TEMPLATES-BLOCK-1/=" ../code-input.js | head -1) - 1)) ../code-input.js >> code-input.mjs
head -n $(($(sed -n "/ESM-SUPPORT-START-TEMPLATES-BLOCK-1/=" ../code-input.js | head -n 1) - 1)) ../code-input.js >> code-input.mjs
# Code before second templates block, after first templates block
head -$(($(sed -n "/ESM-SUPPORT-START-TEMPLATES-BLOCK-2/=" ../code-input.js | head -1) - 1)) ../code-input.js | tail --line=+$(($(sed -n "/ESM-SUPPORT-END-TEMPLATES-BLOCK-1/=" ../code-input.js | head -1) + 1)) >> code-input.mjs
head -n $(($(sed -n "/ESM-SUPPORT-START-TEMPLATES-BLOCK-2/=" ../code-input.js | head -n 1) - 1)) ../code-input.js | tail --line=+$(($(sed -n "/ESM-SUPPORT-END-TEMPLATES-BLOCK-1/=" ../code-input.js | head -n 1) + 1)) >> code-input.mjs
# Code after second templates block
tail --line=+$(($(sed -n "/ESM-SUPPORT-END-TEMPLATES-BLOCK-2/=" ../code-input.js | head -1) + 1)) ../code-input.js >> code-input.mjs
tail --line=+$(($(sed -n "/ESM-SUPPORT-END-TEMPLATES-BLOCK-2/=" ../code-input.js | head -n 1) + 1)) ../code-input.js >> code-input.mjs
# Exports
echo "export const Plugin = codeInput.Plugin;" >> code-input.mjs
echo "export const Template = codeInput.Template;" >> code-input.mjs
Expand All @@ -27,12 +27,39 @@ AUTOGENERATED_NOTICE="// NOTICE: This code is @generated from code outside the e
echo "" >> code-input.d.mts
# Miss out no-ESM specific code at the top
# Code before first namespace, after no-ESM specific code
head -$(($(sed -n "/ESM-SUPPORT-START-NAMESPACE-1/=" ../code-input.d.ts | head -1) - 1)) ../code-input.d.ts | tail --line=+$(($(sed -n "/ESM-SUPPORT-END-NOESM-SPECIFIC/=" ../code-input.d.ts | head -1) + 1)) >> code-input.d.mts
head -n $(($(sed -n "/ESM-SUPPORT-START-NAMESPACE-1/=" ../code-input.d.ts | head -n 1) - 1)) ../code-input.d.ts | tail --line=+$(($(sed -n "/ESM-SUPPORT-END-NOESM-SPECIFIC/=" ../code-input.d.ts | head -n 1) + 1)) >> code-input.d.mts
# Code before second namespace, after first namespace
head -$(($(sed -n "/ESM-SUPPORT-START-NAMESPACE-2/=" ../code-input.d.ts | head -1) - 1)) ../code-input.d.ts | tail --line=+$(($(sed -n "/ESM-SUPPORT-END-NAMESPACE-1/=" ../code-input.d.ts | head -1) + 1)) >> code-input.d.mts
head -n $(($(sed -n "/ESM-SUPPORT-START-NAMESPACE-2/=" ../code-input.d.ts | head -n 1) - 1)) ../code-input.d.ts | tail --line=+$(($(sed -n "/ESM-SUPPORT-END-NAMESPACE-1/=" ../code-input.d.ts | head -n 1) + 1)) >> code-input.d.mts
# Code after second namespace
tail --line=+$(($(sed -n "/ESM-SUPPORT-END-NAMESPACE-2/=" ../code-input.d.ts | head -1) + 1)) ../code-input.d.ts >> code-input.d.mts
echo "export default { Plugin, Template, CodeInput, registerTemplate };" >> code-input.d.mts
tail --line=+$(($(sed -n "/ESM-SUPPORT-END-NAMESPACE-2/=" ../code-input.d.ts | head -n 1) + 1)) ../code-input.d.ts >> code-input.d.mts
echo "

// Prepare the default export:

// Values under the default export
declare const _default: {
Plugin: typeof Plugin;
Template: typeof Template;
CodeInput: typeof CodeInput;
registerTemplate: typeof registerTemplate;
}

// Type aliases to prevent ambiguous 'Plugin = Plugin'
declare type _Plugin = Plugin;
declare type _Template = Template;
declare type _CodeInput = CodeInput;
// Types under the default export
declare namespace _default {
export type Plugin = _Plugin;
export type Template = _Template;
export type CodeInput = _CodeInput;
}

export default _default;" >> code-input.d.mts
#declare type _default.Plugin = Plugin;
#declare type _default.Template = Template;
#declare type _default.CodeInput = CodeInput;


# Templates
mkdir -p templates
Expand All @@ -45,9 +72,9 @@ mkdir -p templates
echo "import { Template } from \"../code-input.mjs\";" >> templates/$0.mjs

# Code after start and before end of this template, making use of the imported Template, not codeInput.Template
head -$(($(sed -n "/ESM-SUPPORT-END-TEMPLATE-$0/=" ../code-input.js | head -1) - 1)) ../code-input.js | tail --line=+$(($(sed -n "/ESM-SUPPORT-START-TEMPLATE-$0/=" ../code-input.js | head -1) + 1)) | sed "s/codeInput\.Template/Template/g" >> templates/$0.mjs
head -n $(($(sed -n "/ESM-SUPPORT-END-TEMPLATE-$0/=" ../code-input.js | head -n 1) - 1)) ../code-input.js | tail --line=+$(($(sed -n "/ESM-SUPPORT-START-TEMPLATE-$0/=" ../code-input.js | head -n 1) + 1)) | sed "s/codeInput\.Template/Template/g" >> templates/$0.mjs

TEMPLATE_CLASS_NAME="$(grep -Eo "class [a-zA-Z]+ extends Template" templates/$0.mjs | head -1 | sed "s/class //" | sed "s/ extends Template//")";
TEMPLATE_CLASS_NAME="$(grep -Eo "class [a-zA-Z]+ extends Template" templates/$0.mjs | head -n 1 | sed "s/class //" | sed "s/ extends Template//")";
# Export.
echo "export default $TEMPLATE_CLASS_NAME;" >> templates/$0.mjs

Expand All @@ -59,10 +86,10 @@ mkdir -p templates
echo $1 > templates/$0.d.mts;
echo "" >> templates/$0.d.mts;
# Imports
echo "import { Template, Plugin } from \"../code-input.d.mts\";" >> templates/$0.d.mts
echo "import type { Template, Plugin } from \"../code-input.d.mts\";" >> templates/$0.d.mts
# Code after start and before end of this template, making use of the imported Template, not codeInput.Template, and the imported Plugin, not codeInput.Plugin, exporting the class as default
# export default class replacement should work but won"t leave indentation as JS version does.
head -$(($(sed -n "/ESM-SUPPORT-END-TEMPLATE-$0/=" ../code-input.d.ts | head -1) - 1)) ../code-input.d.ts | tail --line=+$(($(sed -n "/ESM-SUPPORT-START-TEMPLATE-$0/=" ../code-input.d.ts | head -1) + 1)) | sed "s/codeInput\.Template/Template/g" | sed "s/codeInput\.Plugin/Plugin/g" | sed -E "s/^[[:space:]]*class /export default class /" >> templates/$0.d.mts
head -n $(($(sed -n "/ESM-SUPPORT-END-TEMPLATE-$0/=" ../code-input.d.ts | head -n 1) - 1)) ../code-input.d.ts | tail --line=+$(($(sed -n "/ESM-SUPPORT-START-TEMPLATE-$0/=" ../code-input.d.ts | head -n 1) + 1)) | sed "s/codeInput\.Template/Template/g" | sed "s/codeInput\.Plugin/Plugin/g" | sed -E "s/^[[:space:]]*class /export default class /" >> templates/$0.d.mts

# $0 is the template name, $1 is the autogenerated notice
' "%" "$AUTOGENERATED_NOTICE"
Expand All @@ -77,11 +104,11 @@ mkdir -p plugins
# Imports
echo "import { Plugin } from \"../code-input.mjs\";" >> plugins/$0.mjs
# Plugin syntax is to be stored in an object; do so temporarily.
echo "let plugins = {};" >> plugins/$0.mjs
echo "let plugins = {};" >> plugins/$0.mjs;
# Code from this plugin"s file, making use of the imported Plugin, not codeInput.Plugin, and of the created plugins object, not codeInput.plugins
cat ../plugins/$0.js | sed "s/codeInput\.Plugin/Plugin/g" | sed "s/codeInput\.plugins/plugins/g" >> plugins/$0.mjs;

PLUGIN_CLASS_NAME="$(grep -Eo "codeInput\.plugins\.[a-zA-Z]+" ../plugins/$0.js | head -1 | sed "s/codeInput\.plugins\.//")";
PLUGIN_CLASS_NAME="$(grep -Eo "codeInput\.plugins\.[a-zA-Z]+" ../plugins/$0.js | head -n 1 | sed "s/codeInput\.plugins\.//")";
# Export.
echo "" >> plugins/$0.mjs;
echo "export default plugins.$PLUGIN_CLASS_NAME;" >> plugins/$0.mjs;
Expand All @@ -94,10 +121,21 @@ mkdir -p plugins
echo $1 > plugins/$0.d.mts;
echo "" >> plugins/$0.d.mts;
# Imports
echo "import { Plugin, CodeInput } from \"../code-input.d.mts\";" >> plugins/$0.d.mts
echo "import type { Plugin, CodeInput } from \"../code-input.d.mts\";" >> plugins/$0.d.mts
# Code after start and before end of this template, making use of the imported Plugin, not codeInput.Plugin and the imported CodeInput, not codeInput.CodeInput, exporting the class as default
# export default class replacement should work but won"t leave indentation as JS version does.
head -$(($(sed -n "/ESM-SUPPORT-END-PLUGIN-$0/=" ../code-input.d.ts | head -1) - 1)) ../code-input.d.ts | tail --line=+$(($(sed -n "/ESM-SUPPORT-START-PLUGIN-$0/=" ../code-input.d.ts | head -1) + 1)) | sed "s/codeInput\.Plugin/Plugin/g" | sed "s/codeInput\.CodeInput/CodeInput/g" | sed -E "s/^[[:space:]]*class /export default class /" >> plugins/$0.d.mts
head -n $(($(sed -n "/ESM-SUPPORT-END-PLUGIN-$0/=" ../code-input.d.ts | head -n 1) - 1)) ../code-input.d.ts | tail --line=+$(($(sed -n "/ESM-SUPPORT-START-PLUGIN-$0/=" ../code-input.d.ts | head -n 1) + 1)) >> plugins/$0.d.mts;

# Declare the first class defined in the file and, if a namespace with the same name
# exists, declare that as well, then export it at the end of the file so the class and
# namespace are merged if necessary.
classname=$(grep -Eo "^ *class [A-Za-z]+" plugins/$0.d.mts | head -n 1 | sed "s/^ *class //");

cat plugins/$0.d.mts | sed "s/codeInput\.Plugin/Plugin/g" | sed "s/codeInput\.CodeInput/CodeInput/g" | sed "s/class ${classname} /declare class ${classname} /g" | sed "s/namespace ${classname} /declare namespace ${classname} /g" | sed "s/codeInput\.plugins\.${classname}/${classname}/g" >> plugins/$0.new.d.mts;
# New file in middle so concurrent pipes dont read and write same file
mv plugins/$0.new.d.mts plugins/$0.d.mts;

echo "export default ${classname};" >> plugins/$0.d.mts;

# $0 is the plugin name, $1 is the autogenerated notice
' "%" "$AUTOGENERATED_NOTICE"
7 changes: 7 additions & 0 deletions tests/automated/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# (Semi-)Automated Tests

Carries out partially automated user interface tests to check that both the core components and the plugins work in some ways. It doesn't fully cover every scenario so you should test any code you change by hand, but it's good for quickly checking a wide range of functionality works.

For each of `prism.html` and `hljs.html`, open the page, answer the browser popups you get, and see the results of testing at the end.

The code currently relies on hardcoded wait periods, assuming the interface will respond in time, and meaning that if they don't, tests can fail. If tests fail unexpectedly, free up memory etc. on your computer, reload, and try again.
File renamed without changes.
30 changes: 15 additions & 15 deletions tests/hljs.html → tests/automated/hljs.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,23 @@


<!--Import code-input-->
<link rel="stylesheet" href="../code-input.css">
<script src="../code-input.js"></script>
<link rel="stylesheet" href="../../code-input.css">
<script src="../../code-input.js"></script>

<!--Import code-input plugins-->
<script src="../plugins/auto-close-brackets.js"></script>
<script src="../plugins/autocomplete.js"></script>
<link rel="stylesheet" href="../plugins/autocomplete.css">
<link rel="stylesheet" href="../plugins/autogrow.css">
<script src="../plugins/autodetect.js"></script>
<script src="../plugins/find-and-replace.js"></script>
<link rel="stylesheet" href="../plugins/find-and-replace.css">
<script src="../plugins/go-to-line.js"></script>
<link rel="stylesheet" href="../plugins/go-to-line.css">
<script src="../plugins/indent.js"></script>
<script src="../plugins/select-token-callbacks.js"></script>
<script src="../plugins/special-chars.js"></script>
<link rel="stylesheet" href="../plugins/special-chars.css">
<script src="../../plugins/auto-close-brackets.js"></script>
<script src="../../plugins/autocomplete.js"></script>
<link rel="stylesheet" href="../../plugins/autocomplete.css">
<link rel="stylesheet" href="../../plugins/autogrow.css">
<script src="../../plugins/autodetect.js"></script>
<script src="../../plugins/find-and-replace.js"></script>
<link rel="stylesheet" href="../../plugins/find-and-replace.css">
<script src="../../plugins/go-to-line.js"></script>
<link rel="stylesheet" href="../../plugins/go-to-line.css">
<script src="../../plugins/indent.js"></script>
<script src="../../plugins/select-token-callbacks.js"></script>
<script src="../../plugins/special-chars.js"></script>
<link rel="stylesheet" href="../../plugins/special-chars.css">

<script src="tester.js"></script>
</head>
Expand Down
Loading