mirror of
https://github.com/donlon/cloudflare-error-page.git
synced 2025-12-25 01:39:18 +00:00
move nodejs folder to javascript
This commit is contained in:
4
javascript/src/assets.d.ts
vendored
Normal file
4
javascript/src/assets.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
declare module "./templates/*" {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
||||
101
javascript/src/index.ts
Normal file
101
javascript/src/index.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import * as ejs from "ejs";
|
||||
|
||||
import templateString from "./templates/template.ejs";
|
||||
import cssString from "./templates/main.css";
|
||||
|
||||
export interface StatusItem {
|
||||
status?: "ok" | "error";
|
||||
status_text?: string;
|
||||
status_text_color?: string;
|
||||
location?: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export interface MoreInformation {
|
||||
hidden?: boolean;
|
||||
link?: string;
|
||||
text?: string;
|
||||
for?: string;
|
||||
}
|
||||
|
||||
export interface PerfSecBy {
|
||||
link?: string;
|
||||
text?: string;
|
||||
}
|
||||
|
||||
export interface CreatorInfo {
|
||||
hidden?: boolean;
|
||||
link?: string;
|
||||
text?: string;
|
||||
}
|
||||
|
||||
export interface ErrorPageParams {
|
||||
error_code?: number;
|
||||
title?: string;
|
||||
html_title?: string;
|
||||
time?: string;
|
||||
ray_id?: string;
|
||||
client_ip?: string;
|
||||
|
||||
browser_status?: StatusItem;
|
||||
cloudflare_status?: StatusItem;
|
||||
host_status?: StatusItem;
|
||||
|
||||
error_source?: "browser" | "cloudflare" | "host";
|
||||
|
||||
what_happened?: string;
|
||||
what_can_i_do?: string;
|
||||
|
||||
more_information?: MoreInformation;
|
||||
perf_sec_by?: PerfSecBy;
|
||||
creator_info?: CreatorInfo;
|
||||
}
|
||||
|
||||
// Load EJS template
|
||||
export const baseTemplate: ejs.TemplateFunction = ejs.compile(templateString);
|
||||
|
||||
/**
|
||||
* Generate random hex string for ray-id
|
||||
*/
|
||||
function genHexString(digits: number): string {
|
||||
const hex = "0123456789ABCDEF";
|
||||
let output = "";
|
||||
for (let i = 0; i < digits; i++) {
|
||||
output += hex.charAt(Math.floor(Math.random() * hex.length));
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a customized Cloudflare error page
|
||||
* @param params - The parameters for the error page
|
||||
* @param allowHtml - Whether to allow HTML in what_happened and what_can_i_do fields (default: true)
|
||||
* @param moreArgs - More arguments passed to ejs template
|
||||
* @returns The rendered HTML string
|
||||
*/
|
||||
export function render(
|
||||
params: ErrorPageParams,
|
||||
allowHtml: boolean = true,
|
||||
moreArgs: {
|
||||
[name: string]: any;
|
||||
} = {}
|
||||
): string {
|
||||
params = { ...params };
|
||||
|
||||
if (!params.time) {
|
||||
const now = new Date();
|
||||
params.time = now.toISOString().replace("T", " ").substring(0, 19) + " UTC";
|
||||
}
|
||||
if (!params.ray_id) {
|
||||
params.ray_id = genHexString(16);
|
||||
}
|
||||
|
||||
if (!allowHtml) {
|
||||
params.what_happened = ejs.escapeXML(params.what_happened ?? "");
|
||||
params.what_can_i_do = ejs.escapeXML(params.what_can_i_do ?? "");
|
||||
}
|
||||
|
||||
return baseTemplate({ params, html_style: cssString, ...moreArgs });
|
||||
}
|
||||
|
||||
export default render;
|
||||
1
javascript/src/templates/.gitignore
vendored
Normal file
1
javascript/src/templates/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
main.css
|
||||
110
javascript/src/templates/template.ejs
Normal file
110
javascript/src/templates/template.ejs
Normal file
@@ -0,0 +1,110 @@
|
||||
<!DOCTYPE html>
|
||||
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if IE 7]> <html class="no-js ie7 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en-US"> <!--<![endif]-->
|
||||
<head>
|
||||
<% const error_code = params.error_code || 500; %>
|
||||
<% const title = params.title || 'Internal server error'; %>
|
||||
<% const html_title = params.html_title || (error_code + ': ' + title); %>
|
||||
<title><%= html_title %></title>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||
<meta name="robots" content="noindex, nofollow" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<style>
|
||||
<%- html_style %>
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="cf-wrapper">
|
||||
<div id="cf-error-details" class="p-0">
|
||||
<header class="mx-auto pt-10 lg:pt-6 lg:px-8 w-240 lg:w-full mb-8">
|
||||
<h1 class="inline-block sm:block sm:mb-2 font-light text-60 lg:text-4xl text-black-dark leading-tight mr-2">
|
||||
<span class="inline-block"><%= title %></span>
|
||||
<span class="code-label">Error code <%= error_code %></span>
|
||||
</h1>
|
||||
<% const more_info = params.more_information || {}; %>
|
||||
<% if (!more_info.hidden) { %>
|
||||
<div>
|
||||
Visit <a href="<%= more_info.link || 'https://www.cloudflare.com/' %>" target="_blank" rel="noopener noreferrer"><%= more_info.text || 'cloudflare.com' %></a> for <%= more_info.for || 'more information' %>.
|
||||
</div>
|
||||
<% } %>
|
||||
<div class="<%= more_info.hidden ? '' : 'mt-3' %>"><%= params.time %></div>
|
||||
</header>
|
||||
<div class="my-8 bg-gradient-gray">
|
||||
<div class="w-240 lg:w-full mx-auto">
|
||||
<div class="clearfix md:px-8">
|
||||
<%
|
||||
const items = [
|
||||
{ id: 'browser', icon: 'browser', default_location: 'You', default_name: 'Browser' },
|
||||
{ id: 'cloudflare', icon: 'cloud', default_location: 'San Francisco', default_name: 'Cloudflare' },
|
||||
{ id: 'host', icon: 'server', default_location: 'Website', default_name: 'Host' }
|
||||
];
|
||||
items.forEach(({ id, icon, default_location, default_name }) => {
|
||||
const item = params[id + '_status'] || {};
|
||||
const status = item.status || 'ok';
|
||||
let text_color;
|
||||
if (item.status_text_color) {
|
||||
text_color = item.status_text_color;
|
||||
} else if (status === 'ok') {
|
||||
text_color = '#9bca3e'; // text-green-success
|
||||
} else if (status === 'error') {
|
||||
text_color = '#bd2426'; // text-red-error
|
||||
}
|
||||
const status_text = item.status_text || (status === 'ok' ? 'Working' : 'Error');
|
||||
const is_error_source = params.error_source === id;
|
||||
%>
|
||||
<div id="cf-<%= id %>-status" class="<%= is_error_source ? 'cf-error-source' : '' %> relative w-1/3 md:w-full py-15 md:p-0 md:py-8 md:text-left md:border-solid md:border-0 md:border-b md:border-gray-400 overflow-hidden float-left md:float-none text-center">
|
||||
<div class="relative mb-10 md:m-0">
|
||||
<span class="cf-icon-<%= icon %> block md:hidden h-20 bg-center bg-no-repeat"></span>
|
||||
<span class="cf-icon-<%= status %> w-12 h-12 absolute left-1/2 md:left-auto md:right-0 md:top-0 -ml-6 -bottom-4"></span>
|
||||
</div>
|
||||
<span class="md:block w-full truncate"><%= item.location || default_location %></span>
|
||||
<h3 class="md:inline-block mt-3 md:mt-0 text-2xl text-gray-600 font-light leading-1.3" <%- (item.name || default_name) === 'Cloudflare' ? 'style="color: #2f7bbf;"' : '' %>><%= item.name || default_name %></h3>
|
||||
<span class="leading-1.3 text-2xl" style="color: <%= text_color %>"><%= status_text %></span>
|
||||
</div>
|
||||
<% }); %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w-240 lg:w-full mx-auto mb-8 lg:px-8">
|
||||
<div class="clearfix">
|
||||
<div class="w-1/2 md:w-full float-left pr-6 md:pb-10 md:pr-0 leading-relaxed">
|
||||
<h2 class="text-3xl font-normal leading-1.3 mb-4">What happened?</h2>
|
||||
<%- params.what_happened || '<p>There is an internal server error on Cloudflare\'s network.</p>' %>
|
||||
</div>
|
||||
<div class="w-1/2 md:w-full float-left leading-relaxed">
|
||||
<h2 class="text-3xl font-normal leading-1.3 mb-4">What can I do?</h2>
|
||||
<%- params.what_can_i_do || '<p>Please try again in a few minutes.</p>' %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cf-error-footer cf-wrapper w-240 lg:w-full py-10 sm:py-4 sm:px-8 mx-auto text-center sm:text-left border-solid border-0 border-t border-gray-300">
|
||||
<p class="text-13">
|
||||
<span class="cf-footer-item sm:block sm:mb-1">Ray ID: <strong class="font-semibold"><%= params.ray_id %></strong></span>
|
||||
<span class="cf-footer-separator sm:hidden">•</span>
|
||||
<span id="cf-footer-item-ip" class="cf-footer-item hidden sm:block sm:mb-1">
|
||||
Your IP:
|
||||
<button type="button" id="cf-footer-ip-reveal" class="cf-footer-ip-reveal-btn">Click to reveal</button>
|
||||
<span class="hidden" id="cf-footer-ip"><%= params.client_ip || '1.1.1.1' %></span>
|
||||
<span class="cf-footer-separator sm:hidden">•</span>
|
||||
</span>
|
||||
<% const perf_sec_by = params.perf_sec_by || {}; %>
|
||||
<span class="cf-footer-item sm:block sm:mb-1"><span>Performance & security by</span> <a rel="noopener noreferrer" href="<%= perf_sec_by.link || 'https://www.cloudflare.com/' %>" id="brand_link" target="_blank"><%= perf_sec_by.text || 'Cloudflare' %></a></span>
|
||||
|
||||
<% const creator_info = params.creator_info || {}; %>
|
||||
<% if (!(creator_info.hidden ?? true)) { %>
|
||||
<span class="cf-footer-separator sm:hidden">•</span>
|
||||
<span class="cf-footer-item sm:block sm:mb-1">Created with <a href="<%= creator_info.link %>" target="_blank"><%= creator_info.text %></a></span>
|
||||
<% } %>
|
||||
</p>
|
||||
</div><!-- /.error-footer -->
|
||||
</div>
|
||||
</div>
|
||||
<script>(function(){function d(){var b=a.getElementById("cf-footer-item-ip"),c=a.getElementById("cf-footer-ip-reveal");b&&"classList"in b&&(b.classList.remove("hidden"),c.addEventListener("click",function(){c.classList.add("hidden");a.getElementById("cf-footer-ip").classList.remove("hidden")}))}var a=document;document.addEventListener&&a.addEventListener("DOMContentLoaded",d)})();</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user