Compare commits
7
Commits
53bb02063a
..
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b78eb3f0f4 | ||
|
|
77d96bdfd9 | ||
|
|
851171609b | ||
|
|
a45a0a6368 | ||
|
|
032e551858 | ||
|
|
a3192ec559 | ||
|
|
826daabc72 |
No files matched your search
@@ -0,0 +1,3 @@
|
|||||||
|
# Art
|
||||||
|
|
||||||
|
Support directory to store images which are used inderectly for the site.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# Assets
|
||||||
|
|
||||||
|
Similar to `static/` on a Hugo website, these files are served at the website's
|
||||||
|
root as-is. Useful for favicon type content. Can have folders if desired.
|
||||||
@@ -33,9 +33,9 @@ const asset_types = ['png', 'svg', 'ico', 'webmanifest', 'jpg'];
|
|||||||
let ports = [];
|
let ports = [];
|
||||||
// Check parameters for numeric port numbers.
|
// Check parameters for numeric port numbers.
|
||||||
process.argv.forEach(function (val, index, array) {
|
process.argv.forEach(function (val, index, array) {
|
||||||
console.log("Parameter", index + ':', val, !isNaN(val));
|
console.log(now() + ": Parameter", index + ':', val, !isNaN(val));
|
||||||
if (!isNaN(val)) {
|
if (!isNaN(val)) {
|
||||||
console.log("Adding Port", val)
|
console.log(now() + ": Adding Port", val)
|
||||||
ports.push(val);
|
ports.push(val);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -96,16 +96,21 @@ function getMIME(extension) {
|
|||||||
return mime;
|
return mime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print datetime for logging.
|
||||||
|
function now() {
|
||||||
|
return new Date().toISOString();
|
||||||
|
}
|
||||||
|
|
||||||
/* Code exists inside a main function so that we may use async/await.
|
/* Code exists inside a main function so that we may use async/await.
|
||||||
*/
|
*/
|
||||||
async function main() {
|
async function main() {
|
||||||
console.log("...Starting Main...");
|
console.log(now() + ": ...Starting Main...");
|
||||||
|
|
||||||
// Getting dates in Node.js is awful, just use Linux.
|
// Getting dates in Node.js is awful, just use Linux.
|
||||||
const start_datetime = "" + await execSync('date "+%Y-%m-%dT%H:%M:%S%:z"');
|
const start_datetime = "" + await execSync('date "+%Y-%m-%dT%H:%M:%S%:z"');
|
||||||
const start_datetime_trimmed = start_datetime.trim();
|
const start_datetime_trimmed = start_datetime.trim();
|
||||||
|
|
||||||
console.log("Set app to return HTML documents.");
|
console.log(now() + ": Set app to return HTML documents.");
|
||||||
app.use(function (req, res, next) {
|
app.use(function (req, res, next) {
|
||||||
res.contentType('text/html');
|
res.contentType('text/html');
|
||||||
next();
|
next();
|
||||||
@@ -114,7 +119,7 @@ async function main() {
|
|||||||
/* Loop through all files in the pages subdirectory and add the allowed
|
/* Loop through all files in the pages subdirectory and add the allowed
|
||||||
// file types into the pages array for automatic router creation.
|
// file types into the pages array for automatic router creation.
|
||||||
*/
|
*/
|
||||||
console.log("...Starting Main...");
|
console.log(now() + ": ...Starting Pages...");
|
||||||
let ls = await fs.promises.readdir(pages_dir);
|
let ls = await fs.promises.readdir(pages_dir);
|
||||||
if (DEBUG) console.log("DEBUG: Results of ls, ", ls);
|
if (DEBUG) console.log("DEBUG: Results of ls, ", ls);
|
||||||
for (let file of ls) {
|
for (let file of ls) {
|
||||||
@@ -124,18 +129,19 @@ async function main() {
|
|||||||
if (file_types.includes(file_type)) {
|
if (file_types.includes(file_type)) {
|
||||||
if (DEBUG) console.log("DEBUG: Hooray!", file, "is being added.");
|
if (DEBUG) console.log("DEBUG: Hooray!", file, "is being added.");
|
||||||
pages[file_name] = pages_dir + file;
|
pages[file_name] = pages_dir + file;
|
||||||
console.log(" * Added page", file);
|
console.log(now() + ": * Added page", file);
|
||||||
} else {
|
} else {
|
||||||
if (DEBUG) console.log("DEBUG: ", file, "is not an approved type, skipping.");
|
if (DEBUG) console.log("DEBUG: ", file, "is not an approved type, skipping.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(" * Pages loaded: ", pages);
|
console.log(now() + ": * Pages loaded: ", pages);
|
||||||
//return; // Stop execution FORTESTING
|
//return; // Stop execution FORTESTING
|
||||||
|
|
||||||
/* Loop through the assets folder and grab favicons, manifests, etc. and
|
/* Loop through the assets folder and grab favicons, manifests, etc. and
|
||||||
// allow them to be accessed via the root of the website, such as a favicon
|
// allow them to be accessed via the root of the website, such as a favicon
|
||||||
// at 'https://hyperling.com/favicon.ico'. May help with SEO!
|
// at 'https://hyperling.com/favicon.ico'. May help with SEO!
|
||||||
*/
|
*/
|
||||||
|
console.log(now() + ": ...Starting Assets...");
|
||||||
let ls_assets = await fs.promises.readdir(asset_dir);
|
let ls_assets = await fs.promises.readdir(asset_dir);
|
||||||
if (DEBUG) console.log("DEBUG: Results of ls_assets, ", ls_assets);
|
if (DEBUG) console.log("DEBUG: Results of ls_assets, ", ls_assets);
|
||||||
for (let file of ls_assets) {
|
for (let file of ls_assets) {
|
||||||
@@ -145,12 +151,12 @@ async function main() {
|
|||||||
if (asset_types.includes(file_type)) {
|
if (asset_types.includes(file_type)) {
|
||||||
if (DEBUG) console.log("DEBUG: Hooray!", file, "is being added.");
|
if (DEBUG) console.log("DEBUG: Hooray!", file, "is being added.");
|
||||||
assets[file] = asset_dir + file;
|
assets[file] = asset_dir + file;
|
||||||
console.log(" * Added asset", file);
|
console.log(now() + ": * Added asset", file);
|
||||||
} else {
|
} else {
|
||||||
if (DEBUG) console.log("DEBUG: ", file, "is not an approved type, skipping.");
|
if (DEBUG) console.log("DEBUG: ", file, "is not an approved type, skipping.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(" * Assets loaded: ", assets);
|
console.log(now() + ": * Assets loaded: ", assets);
|
||||||
|
|
||||||
/* Create both an XML and HTML sitemap based on these entries. XML is used for
|
/* Create both an XML and HTML sitemap based on these entries. XML is used for
|
||||||
// bots like SEO scrapers. HTML will be for human users looking for a list of
|
// bots like SEO scrapers. HTML will be for human users looking for a list of
|
||||||
@@ -212,7 +218,7 @@ async function main() {
|
|||||||
Sitemap: https://hyperling.com/sitemap.xml
|
Sitemap: https://hyperling.com/sitemap.xml
|
||||||
`;
|
`;
|
||||||
|
|
||||||
console.log("...Adding Routes...");
|
console.log(now() + ": ...Adding Routes...");
|
||||||
let router = express.Router();
|
let router = express.Router();
|
||||||
|
|
||||||
/* AUTOMATIC METHOD BASED ON OBJECT/ARRAY OF WEB SCRIPTS
|
/* AUTOMATIC METHOD BASED ON OBJECT/ARRAY OF WEB SCRIPTS
|
||||||
@@ -220,9 +226,9 @@ async function main() {
|
|||||||
*/
|
*/
|
||||||
// TBD/TODO would be great to log this as "DATE: ADDRESS hit ROUTER requesting RESOURCE"
|
// TBD/TODO would be great to log this as "DATE: ADDRESS hit ROUTER requesting RESOURCE"
|
||||||
for (let key in pages) {
|
for (let key in pages) {
|
||||||
console.log(" * Creating router for", key);
|
console.log(now() + ": * Creating router for", key);
|
||||||
router.get("/" + key, async function (req,res) {
|
router.get("/" + key, async function (req,res) {
|
||||||
console.log(key, "fulfilling request to", req.socket.remoteAddress, "asking for", req.url);
|
console.log(now() + ":", key, "fulfilling request to", req.socket.remoteAddress, "asking for", req.url);
|
||||||
let html = "" + execSync(pages[key]);
|
let html = "" + execSync(pages[key]);
|
||||||
stringsToRemove.forEach(string => {
|
stringsToRemove.forEach(string => {
|
||||||
html = html.replace(string, "");
|
html = html.replace(string, "");
|
||||||
@@ -233,7 +239,7 @@ async function main() {
|
|||||||
|
|
||||||
/* Append the page to the sitemap variables.
|
/* Append the page to the sitemap variables.
|
||||||
*/
|
*/
|
||||||
console.log(" * * Adding to sitemap.xml");
|
console.log(now() + ": * * Adding to sitemap.xml");
|
||||||
sitemap_xml = sitemap_xml + `
|
sitemap_xml = sitemap_xml + `
|
||||||
<url>
|
<url>
|
||||||
<loc>https://hyperling.com/`+key+`/</loc>
|
<loc>https://hyperling.com/`+key+`/</loc>
|
||||||
@@ -241,7 +247,7 @@ async function main() {
|
|||||||
<priority>0.80</priority>
|
<priority>0.80</priority>
|
||||||
</url>
|
</url>
|
||||||
`;
|
`;
|
||||||
console.log(" * * Adding to sitemap.html");
|
console.log(now() + ": * * Adding to sitemap.html");
|
||||||
sitemap_html = sitemap_html + `
|
sitemap_html = sitemap_html + `
|
||||||
<li>
|
<li>
|
||||||
<b>`+key+`</b>
|
<b>`+key+`</b>
|
||||||
@@ -260,11 +266,11 @@ async function main() {
|
|||||||
</ul></body></html>
|
</ul></body></html>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
console.log(" * Creating routers for assets");
|
console.log(now() + ": * Creating routers for assets");
|
||||||
for (let key in assets) {
|
for (let key in assets) {
|
||||||
console.log(" * * Adding /" + key);
|
console.log(now() + ": * * Adding /" + key);
|
||||||
router.get('/' + key, function (req, res) {
|
router.get('/' + key, function (req, res) {
|
||||||
console.log("asset response to", req.socket.remoteAddress, "asking for", req.url)
|
console.log(now() + ": asset response to", req.socket.remoteAddress, "asking for", req.url)
|
||||||
|
|
||||||
// Build variables.
|
// Build variables.
|
||||||
const file = "./assets/" + req.path;
|
const file = "./assets/" + req.path;
|
||||||
@@ -286,34 +292,34 @@ async function main() {
|
|||||||
|
|
||||||
// Provide sitemap.xml file for "SEO".
|
// Provide sitemap.xml file for "SEO".
|
||||||
// TBD/TODO would be great to log this as "DATE: ADDRESS hit ROUTER requesting RESOURCE"
|
// TBD/TODO would be great to log this as "DATE: ADDRESS hit ROUTER requesting RESOURCE"
|
||||||
console.log(" * Creating router for sitemap.xml");
|
console.log(now() + ": * Creating router for sitemap.xml");
|
||||||
router.get('/sitemap.xml', function (req, res) {
|
router.get('/sitemap.xml', function (req, res) {
|
||||||
console.log("sitemap.xml being provided to", req.socket.remoteAddress)
|
console.log(now() + ": sitemap.xml being provided to", req.socket.remoteAddress)
|
||||||
res.contentType('text/xml');
|
res.contentType('text/xml');
|
||||||
res.send(sitemap_xml);
|
res.send(sitemap_xml);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Provide human-usable sitemap links.
|
// Provide human-usable sitemap links.
|
||||||
// TBD/TODO would be great to log this as "DATE: ADDRESS hit ROUTER requesting RESOURCE"
|
// TBD/TODO would be great to log this as "DATE: ADDRESS hit ROUTER requesting RESOURCE"
|
||||||
console.log(" * Creating router for sitemap*");
|
console.log(now() + ": * Creating router for sitemap*");
|
||||||
router.get('/sitemap*', async function (req, res) {
|
router.get('/sitemap*', async function (req, res) {
|
||||||
console.log("sitemap.html being provided to", req.socket.remoteAddress)
|
console.log(now() + ": sitemap.html being provided to", req.socket.remoteAddress)
|
||||||
html = await mini(sitemap_html);
|
html = await mini(sitemap_html);
|
||||||
res.send(mini(html));
|
res.send(mini(html));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Provide a robots.txt for where search engines should find things.
|
// Provide a robots.txt for where search engines should find things.
|
||||||
console.log(" * Creating router for robots.txt");
|
console.log(now() + ": * Creating router for robots.txt");
|
||||||
router.get('/robots.txt', function (req, res) {
|
router.get('/robots.txt', function (req, res) {
|
||||||
console.log("robots.txt being provided to", req.socket.remoteAddress)
|
console.log(now() + ": robots.txt being provided to", req.socket.remoteAddress)
|
||||||
res.send(robots_txt);
|
res.send(robots_txt);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Return a resource from the files folder.
|
// Return a resource from the files folder.
|
||||||
// TBD/TODO would be great to log this as "DATE: ADDRESS hit ROUTER requesting RESOURCE"
|
// TBD/TODO would be great to log this as "DATE: ADDRESS hit ROUTER requesting RESOURCE"
|
||||||
console.log(" * Creating router for files");
|
console.log(now() + ": * Creating router for files");
|
||||||
router.get('/files*', function (req, res) {
|
router.get('/files*', function (req, res) {
|
||||||
console.log("file response to", req.socket.remoteAddress, "asking for", req.url)
|
console.log(now() + ": file response to", req.socket.remoteAddress, "asking for", req.url)
|
||||||
|
|
||||||
// Build variables.
|
// Build variables.
|
||||||
const file = "." + req.path;
|
const file = "." + req.path;
|
||||||
@@ -333,12 +339,12 @@ async function main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Originally a test, now a catch-all redirection to Home!
|
// Originally a test, now a catch-all redirection to Home!
|
||||||
console.log(" * Creating router for redirection");
|
console.log(now() + ": * Creating router for redirection");
|
||||||
router.get('/*', async function (req, res) {
|
router.get('/*', async function (req, res) {
|
||||||
// WARNING: These are huge so only look when you need to.
|
// WARNING: These are huge so only look when you need to.
|
||||||
//console.log(req);
|
//console.log(req);
|
||||||
//console.log(res);
|
//console.log(res);
|
||||||
console.log("*wildcard* replying to", req.socket.remoteAddress, "asking for", req.url)
|
console.log(now() + ": *wildcard* replying to", req.socket.remoteAddress, "asking for", req.url)
|
||||||
let html = "" + execSync("./pages/home.php");
|
let html = "" + execSync("./pages/home.php");
|
||||||
stringsToRemove.forEach(string => {
|
stringsToRemove.forEach(string => {
|
||||||
html = html.replace(string, "");
|
html = html.replace(string, "");
|
||||||
@@ -349,13 +355,13 @@ async function main() {
|
|||||||
|
|
||||||
app.use('', router);
|
app.use('', router);
|
||||||
|
|
||||||
console.log("...Adding Ports...");
|
console.log(now() + ": ...Adding Ports...");
|
||||||
ports.forEach(port => {
|
ports.forEach(port => {
|
||||||
app.listen(port);
|
app.listen(port);
|
||||||
console.log(" * Now listening on port " + port + ".");
|
console.log(now() + ": * Now listening on port " + port + ".");
|
||||||
console.log(" * URL: http://localhost:" + port);
|
console.log(now() + ": * URL: http://localhost:" + port);
|
||||||
});
|
});
|
||||||
console.log("Done! Now we wait...");
|
console.log(now() + ": Done! Now we wait...");
|
||||||
}
|
}
|
||||||
|
|
||||||
//// Program Execution ////
|
//// Program Execution ////
|
||||||
|
|||||||
+5
-7
@@ -38,7 +38,7 @@
|
|||||||
convenient group:
|
convenient group:
|
||||||
</p>
|
</p>
|
||||||
<ul class="indent"><li>
|
<ul class="indent"><li>
|
||||||
<a href="https://git.hyperling.com/me/env-obtainium-hyperling/raw/branch/prod/obtainium-export.json"
|
<a href="https://git.hyperling.com/me/env-obtainium-hyperling/src/branch/prod/obtainium-export.json"
|
||||||
target="_blank" rel="noopener noreferrer"
|
target="_blank" rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
[obtainium-export.json] | Hyperling's Apps
|
[obtainium-export.json] | Hyperling's Apps
|
||||||
@@ -57,15 +57,13 @@
|
|||||||
section below, here is how to show the correct version numbers:
|
section below, here is how to show the correct version numbers:
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Enable <i>"Sort by only the last segment of the link"</i>.</li>
|
|
||||||
<li>
|
<li>
|
||||||
Set the <i>"Version string extraction RegEx"</i> field to:
|
Set the <i>"Version string extraction RegEx"</i> field to:
|
||||||
<code>[0-9\.]+[0-9]+</code>
|
<code>\d+\.\d+\.\d+</code>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
Otherwise, using <i>"Take first link"</i> ensures you get the
|
That should be all that's needed as of November 2026.
|
||||||
proper update but will show pseudo versions.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -133,12 +131,12 @@
|
|||||||
src="https://git.hyperling.com/me/flutter-sunset-alarm/raw/branch/main/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png"
|
src="https://git.hyperling.com/me/flutter-sunset-alarm/raw/branch/main/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png"
|
||||||
>
|
>
|
||||||
<figcaption>
|
<figcaption>
|
||||||
Sunset Timer
|
Sunset Alarm
|
||||||
</figcaption>
|
</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
</a>
|
</a>
|
||||||
<p>
|
<p>
|
||||||
Set an alarm to go off X minutes before sunset. (Linux & Android)
|
Set an alarm time based on sunset. (Linux & Android)
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
[<a href="https://git.hyperling.com/me/flutter-sunset-alarm/releases/download/latest/sunset_alarm-arm64-v8a-release.apk/"
|
[<a href="https://git.hyperling.com/me/flutter-sunset-alarm/releases/download/latest/sunset_alarm-arm64-v8a-release.apk/"
|
||||||
|
|||||||
+12
-12
@@ -1,20 +1,20 @@
|
|||||||
|
|
||||||
<link rel="icon" sizes="32x32"
|
<!-- Old, no longer needed
|
||||||
href="/favicon.ico"
|
<link rel="icon" sizes="32x32" href="/favicon.ico">
|
||||||
>
|
<link rel="icon" sizes="192x192" href="/favicon.ico">
|
||||||
<link rel="icon" sizes="192x192"
|
-->
|
||||||
href="/favicon.ico"
|
|
||||||
>
|
|
||||||
|
|
||||||
<!-- https://favicon.io -->
|
<!-- https://favicon.io, added the ?v=20261102 manually. -->
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png?v=20261102">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
|
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png?v=20261102">
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
|
<!-- Not needed, covered in the realfavicongenerator section.
|
||||||
<link rel="manifest" href="/site.webmanifest">
|
<link rel="manifest" href="/site.webmanifest">
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
|
||||||
|
-->
|
||||||
|
|
||||||
<!-- https://realfavicongenerator.net -->
|
<!-- https://realfavicongenerator.net , added the sizes=any manually. -->
|
||||||
<link rel="icon" type="image/png" href="/favicon-96x96.png?v=20261102" sizes="96x96" />
|
<link rel="icon" type="image/png" href="/favicon-96x96.png?v=20261102" sizes="96x96" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg?v=20261102" />
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg?v=20261102" sizes="any" />
|
||||||
<link rel="shortcut icon" href="/favicon.ico?v=20261102" />
|
<link rel="shortcut icon" href="/favicon.ico?v=20261102" />
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png?v=20261102" />
|
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png?v=20261102" />
|
||||||
<meta name="apple-mobile-web-app-title" content="Hyperling" />
|
<meta name="apple-mobile-web-app-title" content="Hyperling" />
|
||||||
|
|||||||
Reference in new issue
Block a user