9
0
mirror of https://github.com/donlon/cloudflare-error-page.git synced 2026-01-04 15:31:41 +00:00

editor/web: update code generator

This commit is contained in:
Anthony Donlon
2025-12-23 20:47:21 +08:00
parent f50f81afd1
commit ae8849f39f
8 changed files with 113 additions and 36 deletions

View File

@@ -173,7 +173,7 @@
max-height: 1200px !important;
font-family: monospace;
font-size: 0.8em !important;
overflow: auto;
overflow: hidden;
}
.save-as-dialog__buttons {
@@ -475,7 +475,7 @@
<button type="button" id="btnOpen" class="btn btn-sm btn-primary">Preview in new tab</button>
<!-- Button trigger modal -->
<button type="button" class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#saveAsDialog">
Save as...
Save as & Examples ...
</button>
</div>
@@ -547,7 +547,9 @@
Save
</button>
</div>
<pre id="saveAsDialogCode" class="border px-2 py-1 save-as-dialog__code"></pre>
<div class="border rounded save-as-dialog__code">
<pre id="saveAsDialogCode" class="px-2 py-1 h-100"></pre>
</div>
</div>
</div>
</div>

View File

@@ -1,4 +1,5 @@
import ejs from 'ejs';
import { ErrorPageParams } from 'cloudflare-error-page';
import jsTemplate from './js.ejs?raw';
import jsonTemplate from './json.ejs?raw';
@@ -7,23 +8,97 @@ import pythonTemplate from './python.ejs?raw';
interface CodeGen {
name: string;
language: string;
generate(params: any): string;
generate(params: ErrorPageParams): string;
}
class EjsCodeGen implements CodeGen {
name: string;
language: string;
private template: ejs.TemplateFunction;
constructor(name: string, language: string, templateContent: any) {
constructor(name: string, language: string, templateContent: string) {
this.name = name;
this.language = language;
this.template = ejs.compile(templateContent);
}
generate(params: any): string {
return this.template({ params });
protected prepareTemplateArgs(params: ErrorPageParams): Record<string, any> {
return {};
}
generate(params: ErrorPageParams): string {
const moreArgs = this.prepareTemplateArgs(params);
return this.template({ params, ...moreArgs });
}
}
export const jsCodeGen = new EjsCodeGen('NodeJS Example', 'javascript', jsTemplate);
function getErrorCode(error_code?: string | number) {
const errorCode = error_code || '';
return /\d{3}/.test(errorCode + '') ? errorCode : 500;
}
class JSCodeGen extends EjsCodeGen {
constructor(templateContent: string) {
super('JavaScript Example', 'javascript', templateContent);
}
private formatJSArgs(params: ErrorPageParams): string {
params = { ...params };
const rayIdKey = Math.random() + '';
const clientIpKey = Math.random() + '';
params.ray_id = rayIdKey;
params.client_ip = clientIpKey;
const paramsArg = JSON.stringify(params, null, 2)
.replace(`"${rayIdKey}"`, "(req.get('Cf-Ray') ?? '').substring(0, 16)")
.replace(`"${clientIpKey}"`, "req.get('X-Forwarded-For') || req.socket.remoteAddress");
return paramsArg;
}
protected prepareTemplateArgs(params: ErrorPageParams): Record<string, any> {
return {
errorCode: getErrorCode(params.error_code),
// TODO: format to JS-style object (key w/o parens)
indentedParams: this.formatJSArgs(params).replaceAll('\n', '\n '),
};
}
}
class PythonCodeGen extends EjsCodeGen {
constructor(templateContent: string) {
super('Python Example', 'python', templateContent);
}
private formatPythonArgs(params: ErrorPageParams): string {
// Covert the parameters to Python format object
params = { ...params };
const randomKey = Math.random() + '';
const rayIdKey = Math.random() + '';
const clientIpKey = Math.random() + '';
params.ray_id = rayIdKey;
params.client_ip = clientIpKey;
const paramsArg = JSON.stringify(
params,
(key, value) => {
if (typeof value === 'boolean') {
return randomKey + value.toString();
} else if (value === null) {
return randomKey + 'null';
} else {
return value;
}
},
4
)
.replace(`"${randomKey}true"`, 'True')
.replace(`"${randomKey}false"`, 'False')
.replace(`"${randomKey}null"`, 'None')
.replace(`"${rayIdKey}"`, 'request.headers.get("Cf-Ray", "")[:16]')
.replace(`"${clientIpKey}"`, 'request.headers.get("X-Forwarded-For") or request.remote_addr');
return paramsArg;
}
protected prepareTemplateArgs(params: ErrorPageParams): Record<string, any> {
return {
errorCode: getErrorCode(params.error_code),
// TODO: format to JS-style object (key w/o parens)
indentedParams: this.formatPythonArgs(params).replaceAll('\n', '\n '),
};
}
}
export const jsCodeGen = new JSCodeGen(jsTemplate);
export const jsonCodeGen = new EjsCodeGen('JSON', 'json', jsonTemplate);
export const pythonCodeGen = new EjsCodeGen('Python Example', 'python', pythonTemplate);
export const pythonCodeGen = new PythonCodeGen(pythonTemplate);

View File

@@ -1,3 +1,11 @@
#!/usr/bin/env node
/*
* JavaScript Example: Render and serve the Cloudflare error page using Express server
*
* Prerequisits:
* npm install cloudflare-error-page
*/
import express from 'express';
import { render as render_cf_error_page } from 'cloudflare-error-page';
@@ -5,10 +13,8 @@ const app = express();
const port = 3000;
// Define a route for GET requests to the root URL
<%# TODO: format to JS-style object (key w/o parens) _%>
<% const errorCode = params.error_code || 500 _%>
app.get('/', (req, res) => {
res.status(<%= /\d{3}/.test(errorCode + '') ? errorCode : 500 %>).send(render_cf_error_page(<%-JSON.stringify(params, null, 2).replaceAll('\n', '\n ')%>));
res.status(<%= errorCode %>).send(render_cf_error_page(<%- indentedParams %>));
});
// Start the server and listen on the specified port

View File

@@ -1 +1 @@
<%-JSON.stringify(params, null, 4)%>
<%- JSON.stringify(params, null, 4) %>

View File

@@ -1,31 +1,21 @@
<%
// Covert the parameters to Python format object
const randomKey = Math.random() + ''
const paramsArg = JSON.stringify(params, (key, value) => {
if (typeof value === 'boolean') {
return randomKey + value.toString()
} else if (value === null) {
return randomKey + 'null'
} else {
return value
}
}, 4)
.replace(`"${randomKey}true"`, 'True')
.replace(`"${randomKey}false"`, 'False')
.replace(`"${randomKey}null"`, 'None')
#!/usr/bin/env python3
#
# Python Example: Render and serve the Cloudflare error page using Flask server
#
# Prerequisits:
# pip install cloudflare-error-page
#
const errorCode = params.error_code || 500
_%>
from flask import Flask
from flask import Flask, request
from cloudflare_error_page import render as render_cf_error_page
app = Flask(__name__)
# Define a route for GET requests to the root URL
@app.route('/')
@app.route("/")
def index():
# Render the error page
return render_cf_error_page(<%- paramsArg.replaceAll('\n', '\n ') %>), <%= /\d{3}/.test(errorCode + '') ? errorCode : 500 %>
return render_cf_error_page(<%- indentedParams %>), <%= errorCode %>
if __name__ == '__main__':
if __name__ == "__main__":
app.run(debug=True, port=5000)

View File

@@ -431,6 +431,7 @@ function updateSaveAsDialog(e) {
}
const params = { ...lastCfg };
delete params.time;
delete params.ray_id;
let language;
if (codegen) {
saveAsContent = codegen.generate(params);
@@ -445,6 +446,7 @@ function updateSaveAsDialog(e) {
const html = Prism.highlight(saveAsContent, Prism.languages[language], language);
$('saveAsDialogCode').innerHTML = html;
$('saveAsDialogCode').scrollTop = 0;
document.querySelectorAll('#saveAsDialogTypes button').forEach((element) => {
const isCurrent = element.dataset.type == saveAsType;