diff --git a/Angular/.ci/clean_unix-any.sh b/Angular/.ci/clean_unix-any.sh
index f56216c0..ba89d7a7 100644
--- a/Angular/.ci/clean_unix-any.sh
+++ b/Angular/.ci/clean_unix-any.sh
@@ -31,6 +31,7 @@ cd "${PROJECT_PATH_ROOT}/${PROJECT_ANGULAR}"
FS_Remove_Silently "dist"
FS_Remove_Silently "node_modules"
+FS_Remove_Silently ".angular"
cd "$__current_path"
unset __current_path
diff --git a/Angular/.ci/clean_windows-any.ps1 b/Angular/.ci/clean_windows-any.ps1
index b674830c..8f3549b7 100644
--- a/Angular/.ci/clean_windows-any.ps1
+++ b/Angular/.ci/clean_windows-any.ps1
@@ -30,6 +30,7 @@ $null = Set-Location "${env:PROJECT_PATH_ROOT}\${env:PROJECT_ANGULAR}"
$null = FS-Remove-Silently "dist"
$null = FS-Remove-Silently "node_modules"
+$null = FS-Remove-Silently ".angular"
$null = Set-Location "${__current_path}"
$null = Remove-Variable __current_path
diff --git a/Angular/.ci/test_unix-any.sh b/Angular/.ci/test_unix-any.sh
index e38964f2..8d128f1c 100644
--- a/Angular/.ci/test_unix-any.sh
+++ b/Angular/.ci/test_unix-any.sh
@@ -45,25 +45,7 @@ if [ $(OS_Is_Run_Simulated) -eq 0 ]; then
I18N_Simulate_Testing
return 0
else
- ___old_IFS="$IFS"
- while IFS="" read -r ___line || [ -n "$___line" ]; do
- ___browser="$(type -p chromium)"
- if [ ! -z "$___browser" ]; then
- break
- fi
- done << EOF
-chromium
-google-chrome
-brave-browser
-EOF
- IFS="$___old_IFS" && unset ___old_IFS ___line
-
- if [ "$___browser" = "" ]; then
- I18N_Run_Failed
- return 1
- fi
-
- CHROME_BIN="$___browser" ./test.sh.ps1
+ ./test.sh.ps1
if [ $? -ne 0 ]; then
I18N_Run_Failed
return 1
diff --git a/Angular/.ci/test_windows-any.ps1 b/Angular/.ci/test_windows-any.ps1
index e7966bb5..8df30153 100644
--- a/Angular/.ci/test_windows-any.ps1
+++ b/Angular/.ci/test_windows-any.ps1
@@ -45,13 +45,6 @@ if ($(OS-Is-Run-Simulated) -eq 0) {
$null = I18N-Simulate-Testing
return 0
} else {
- $___browser = Get-Command "chrome.exe" -ErrorAction SilentlyContinue
- if ($(STRINGS-Is-Empty "${___browser}") -eq 0) {
- $null = I18N-Run-Failed
- return 1
- }
- $env:CHROME_BIN = $___browser
-
$___process = OS-Exec "./test.sh.ps1"
if ($___process -ne 0) {
$null = I18N-Run-Failed
diff --git a/Angular/.gitignore b/Angular/.gitignore
index 1874c1ee..236a5680 100644
--- a/Angular/.gitignore
+++ b/Angular/.gitignore
@@ -3,6 +3,15 @@
# (1) Specify your project specific files and directories here. You should #
# only touch this section. #
################################################################################
+services/HestiaFONT_NOTO_EMOJI_COLOR/
+services/HestiaFONT_NOTO_SANS/
+services/HestiaGUI_ANCHOR/
+services/HestiaGUI_BUTTON/
+services/HestiaGUI_CORE/
+services/HestiaGUI_SOCIAL/
+services/HestiaGUI_SOCIAL_BLUESKY/
+services/HestiaGUI_ULIST/
+services/HestiaSOCIAL/
@@ -19,6 +28,8 @@ assets/manifest.webmanifest
assets/robots.txt
assets/sitemap.xml
assets/sitemaps/
+services/app/root.html
+services/app/.root.html
diff --git a/Angular/README.md b/Angular/README.md
index 05e6005c..6df8c42c 100644
--- a/Angular/README.md
+++ b/Angular/README.md
@@ -13,17 +13,17 @@ components directories:
1. `contents/` - organize page components with respect to pathing hirarchy.
2. `services/` - where your libraries and service components stays.
-3. `services/app/` - where `app-root` and `app-footer` components are located.
-4. `services/init/` - where your project init components are located.
+3. `services/app/` - where `app-root`, `app-footer`, and `Init.ts` components
+ are located.
5. `assets/` - any static files located at the root of the site.
-The root directory for the workspace is where both `app.ts` and `app.server.ts`
-are located.
+The root directory for the workspace is where both `main.ts` and
+`main.server.ts` are located.
For internationalization (i18n), it is best to keep it as a service component
libraries while keeping the `contents/` directory as the page template. You can
-pass the language code using the `app.routes.ts` routing mechanism and have
-them rendered accordingly.
+definite and pass the language code using the `app.routes.ts` routing mechanism.
+Then, the page components can render the specific language accordingly.
To avoid path conflicts, you should always check the `assets/` availability
before creating the content inside `content/` directory.
@@ -51,22 +51,33 @@ $ cd Angular/
$ ./serve.sh.ps1 # for development
$ ./test.sh.ps1 # for test run
$ ./build.sh.ps1 # for build
+$ ./watch.sh.ps1 # for watch
```
This is mainly due to Angular does not have any pre-initialization function
-where the workspace's critical data files can be updated dynamically
-(example: `assets/manifest.webmanifest`, `assets/CNAME`, and etc). To workaround
-this, a 2-steps execution is done inside these scripts where the `init.sh.ps1`
-(sourced by the all shell scripts) is responsible for building and updating
-these critical data files using the server-side-rendering.
+to update critical SEO files generations autonomously & dynamically. Affected
+files are:
-Those are Polygot scripts which means it works on both UNIX and Windows OSes
-natively.
+* `assets/browserconfig.xml`
+* `assets/CNAME`
+* `assets/.nojekyll`
+* `assets/sitemap.xml`
+* `assets/robots.txt`
+* `assets/manifest.webmanifest`
+* `services/app/root.html`
+This includes the `index.html` (`services/app/root.html`) that `angular.json`
+depends on. To workaround this issue, a 2-steps execution is done using the
+Shell (and PowerShell on Windows) scripts where Stage-1 is to prepare these
+criticaly files dynamically while Stage-2 is your designated execution.
+Those shell scripts are Polygot in nature so the same script works on both
+UNIX and Windows OSes natively.
-## Server-Side Rendering (SSR) or Static Site Generation (SSG) First
+
+
+## Server-Side Rendering (SSR) or Static Site Generation (SSG) Enabled
AutomataCI prioritizes the SSR and SSG (pre-rendering) facilities over other
modes. There is a high chance this project is likely being used to generate
@@ -103,17 +114,19 @@ To set the base URL, update the `baseHref` and `deployUrl` data inside the
`baseHref` is used as the website base URL while `deployUrl` is for the
asset-only base URL.
-**DO NOT SEND IN ANY OF THEM VIA COMMAND ARGUMENTS**. The workspace
-initialization is only sourcing from `angular.json` data file. Failure can
-cause unknown and time-consuming concequences.
+> **DO NOT SEND IN ANY OF THEM VIA COMMAND ARGUMENTS**
+>
+> The workspace initialization is only sourcing from `angular.json` data file.
+> Failure can cause unknown and time-consuming concequences.
## Site-Level Metadata
-You just need to edit `services/app/metadata.ts` data file that houses the
-site-level metadata. Each fields are documented with inline specifications.
+You just need to edit `services/app/Metadata.ts` data file that houses the
+site-level metadata. Each fields are documented with its inline
+specifications.
@@ -121,8 +134,9 @@ site-level metadata. Each fields are documented with inline specifications.
## PWA Web Manifest
By default, the workspace engine prepares and generates the
-`manifest.webmanifest` file dynamically via the 2-steps operation using the
-`services/app/metadata.ts` data.
+`assets/manifest.webmanifest` file dynamically in the Stage-1 execution.
+
+It generally uses `services/app/Metadata.ts` data for dynamic configurations.
@@ -130,11 +144,12 @@ By default, the workspace engine prepares and generates the
## Site Favicons, Logos, and Screenshots
This workspace defines the favicons, logos, and screenshots metadata in the
-`services/app/metadata.ts` data file ("Icons" section). You can supply the
-media files in the `assets/` directory.
+`services/app/Metadata.ts` data file. You can supply the media files in the
+`assets/` directory (e.g. `assets/screenshots/`, `assets/thumbnails/`,
+`assets/logos/`).
-The default media files are located in `assets/logos/` directory. On the
-first run, you can just update these media files to match your project.
+If you just want to dive in with site construction, simply override the
+existing template files in the `assets/` directory is suffice.
@@ -143,9 +158,15 @@ first run, you can just update these media files to match your project.
By default, AutomataCI setup the default image thumbnails located inside the
`assets/thumbnails/` directory. These images serve as the fall back images
-in case the page-level ones failed.
+in case the page-level ones failed. These default thumbnails are configurable
+in the `services/app/Metadata.ts` file.
-In practice, these Open-Graph metadata must be updated at page-level.
+The `services/app/root.html` (main template file) is dynamically generated
+in Stage-1 execution with the site-level thumbnails meta included.
+
+Currently, Angular updates the meta tags dynamically using `Meta` and `Title`
+services from `@angular/platform-browser` library. There is no way to statically
+generate/patch the output `index.html` file yet.
Recommended media dimension would be:
@@ -153,45 +174,15 @@ Recommended media dimension would be:
2. `1200x1200` - square presentation
3. `480x480` - fallback presentation
-You are free to alter the thumbnails located in `services/app/root.html` head
-section.
-For image, please use:
-```
-
-
-
-
-
-```
-For video, please use:
-
-```
-
-
-
-
-
-```
+## LD+JSON Search Engine Optimization Schematic Data
-For audio, please use:
+This feature is pending and under development.
```
-
-
-```
-
-For more technical specification, please refer to the following:
-
-1. https://ogp.me/
-
-
-
-
-## LD+JSON Search Engine Optimization Schematic Data
-
+SPEC:
By default, AutomataCI only setup the default empty tag in the
`services/app/root.html`.
@@ -200,16 +191,21 @@ For more technical specifications, please refer to the following:
1. https://schema.org/docs/full.html
+For SEO, the default page **MUST** be the root page since Angular only
+pre-render the landing page HTML once and let its Javascript to take over
+the others.
+```
+
## Sitemaps & `Robots.txt` Search Engine Optimization (SEO)
-By default, the engine generates both the sitemaps and the `robots.txt`
-autonomously using the `services/app/metadata.ts` data file via the 2-steps
-operation.
+By default, the engine generates both the sitemaps (`assets/sitemap.xml` and
+the `assets/sitemaps/` directory) and the `assets/robots.txt` autonomously
+using the `services/app/Metadata.ts` data file via Stage-1 execution.
-The engine is designed to utilize sitemap index for large scale contents.
+It uses the sitemap index methodology for large scale contents mapping.
@@ -217,7 +213,8 @@ The engine is designed to utilize sitemap index for large scale contents.
## `browserconfig.xml` fallback configuration
While deemed obselete, this file is generated autonomously for backward
-compatibilities and request silencing via the 2-steps operation.
+compatibilities and silencing the request using the `services/app/Metadata.ts`
+data file via Stage-1 execution.
@@ -226,7 +223,7 @@ compatibilities and request silencing via the 2-steps operation.
Specific to GitHub Pages, the engine generates the `assets/.nojekyll`
configuration file for instructing the facility not to use
-[Jekyll](https://jekyllrb.com/) via the 2-steps operation.
+[Jekyll](https://jekyllrb.com/) via Stage-1 execution.
@@ -234,5 +231,7 @@ configuration file for instructing the facility not to use
## `CNAME` configuration file
Specific to GitHub Pages, the engine generates the `assets/CNAME` config
-file based on the `services/app/metadata.ts` data file. This is used by
-GitHub Pages to implement custom domain configurations.
+file based on the `services/app/Metadata.ts` data file via Stage-1 execution.
+
+This file is used by GitHub Pages to implement custom domain configurations
+persistently.
diff --git a/Angular/app.config.server.ts b/Angular/app.config.server.ts
index 1420c354..c15b6c68 100644
--- a/Angular/app.config.server.ts
+++ b/Angular/app.config.server.ts
@@ -3,6 +3,7 @@
*/
import { mergeApplicationConfig, ApplicationConfig } from '@angular/core';
import { provideServerRendering } from '@angular/platform-server';
+
import { appConfig } from './app.config';
@@ -10,7 +11,7 @@ import { appConfig } from './app.config';
const serverConfig: ApplicationConfig = {
providers: [
- provideServerRendering()
+ provideServerRendering(),
]
};
export const config = mergeApplicationConfig(appConfig, serverConfig);
diff --git a/Angular/app.config.ts b/Angular/app.config.ts
index 79b174de..ec1959b3 100644
--- a/Angular/app.config.ts
+++ b/Angular/app.config.ts
@@ -3,11 +3,43 @@
*/
import { ApplicationConfig, isDevMode } from '@angular/core';
import { provideRouter } from '@angular/router';
-
-import { routes } from './app.routes';
+import { APP_BASE_HREF, PlatformLocation } from '@angular/common';
import { provideClientHydration } from '@angular/platform-browser';
import { provideServiceWorker } from '@angular/service-worker';
+import { routes } from './app.routes';
+
+
+
+
+export function Parse_URL_Base(target: PlatformLocation): string {
+ // try parsing from DOM
+ var output = target.getBaseHrefFromDOM().replace(/\/$/, "");
+ if (output != '') {
+ return output;
+ }
+
+
+ // no choice - construct from protocol, hostname, and port
+ switch (target.protocol) {
+ case 'http:':
+ case 'https:':
+ output = `${target.protocol}//`;
+ break;
+ default:
+ output = `${target.protocol}`;
+ break;
+ }
+
+ output += target.hostname;
+
+ if (target.port != "") {
+ output += `:${target.port}`;
+ }
+
+ return output;
+}
+
@@ -18,6 +50,10 @@ export const appConfig: ApplicationConfig = {
provideServiceWorker('ngsw-worker.js', {
enabled: !isDevMode(),
registrationStrategy: 'registerWhenStable:30000'
- }),
+ }), {
+ provide: APP_BASE_HREF,
+ useFactory: Parse_URL_Base,
+ deps: [PlatformLocation],
+ },
]
};
diff --git a/Angular/app.routes.ts b/Angular/app.routes.ts
index b1366a78..30759f2a 100644
--- a/Angular/app.routes.ts
+++ b/Angular/app.routes.ts
@@ -3,9 +3,11 @@
*/
import { Routes } from '@angular/router';
-import { Page_Root } from "./contents/page";
-import { Page_404 } from "./contents/404/page";
-import { Page_Lang } from "./contents/lang/page";
+import { METADATA_SITE } from "services/app/Metadata";
+
+import { Page_Root } from "contents/Page";
+import { Page_404 } from "contents/404/Page";
+import { Page_Lang } from "contents/lang/Page";
@@ -16,7 +18,7 @@ export const routes: Routes = [
path: '',
component: Page_Root,
data: {
- lang: '',
+ lang: 'en',
},
},
@@ -35,5 +37,8 @@ export const routes: Routes = [
{
path: '**',
component: Page_404,
+ data: {
+ lang: 'en',
+ },
},
];
diff --git a/Angular/build.sh.ps1 b/Angular/build.sh.ps1
index bce75bd6..2df867ea 100755
--- a/Angular/build.sh.ps1
+++ b/Angular/build.sh.ps1
@@ -24,17 +24,13 @@ echo \" <<'RUN_AS_POWERSHELL' >/dev/null # " | Out-Null
################################################################################
# Windows POWERSHELL Codes #
################################################################################
-# execute
-$null = . ".\init.sh.ps1"
-$null = Write-Host "initializing the repository..."
-$null = ng build --aot --configuration production --server main.server.ts | Out-Null
-$null = Remove-Item -Recurse -Force ".\dist" -ErrorAction SilentlyContinue
-$null = [System.IO.File]::FlushAll()
-$null = ng build --aot --configuration production
+${env:WORKSPACE_ROOT} = Get-Location
+${env:WORKSPACE_RUN} = 'production'
+$___process = . "${env:WORKSPACE_ROOT}\services\app\shell\build.ps1"
################################################################################
# Windows POWERSHELL Codes #
################################################################################
-exit
+exit $___process
<#
RUN_AS_POWERSHELL
@@ -44,13 +40,9 @@ RUN_AS_POWERSHELL
################################################################################
# Unix Main Codes #
################################################################################
-# execute
-. "./init.sh.ps1"
-1>&2 printf -- "%s\n" "initializing the repository..."
-ng build --aot --configuration production --server main.server.ts &> /dev/null
-rm -rf "./dist/" &> /dev/null
-sync
-ng build --aot --configuration production
+WORKSPACE_ROOT="$PWD"
+WORKSPACE_RUN="production"
+. "${WORKSPACE_ROOT}/services/app/shell/build.sh"
################################################################################
# Unix Main Codes #
################################################################################
diff --git a/Angular/contents/404/Page.ts b/Angular/contents/404/Page.ts
new file mode 100644
index 00000000..39c0f426
--- /dev/null
+++ b/Angular/contents/404/Page.ts
@@ -0,0 +1,35 @@
+/*
+ * COPYRIGHT LICENSE NOTICE HERE
+ */
+import { Component } from '@angular/core';
+import { RouterOutlet, ActivatedRoute } from '@angular/router';
+
+import { Data_Page } from './data-i18n';
+
+
+
+
+@Component({
+ selector: 'page-404',
+ imports: [RouterOutlet],
+ templateUrl: './page.html',
+ styleUrl: './page.css'
+})
+export class Page_404 {
+ public constructor(
+ private route: ActivatedRoute,
+ public Metadata: Data_Page,
+ ) {
+ this.Metadata.Init(route);
+ }
+
+
+ public ngOnInit() {
+ if (!this.Metadata.Mode_Browser) {
+ // server mode (SSR|SSG|pre-render)
+ return;
+ }
+
+ // browser mode
+ }
+}
diff --git a/Angular/contents/404/data-i18n.ts b/Angular/contents/404/data-i18n.ts
new file mode 100644
index 00000000..aec06d48
--- /dev/null
+++ b/Angular/contents/404/data-i18n.ts
@@ -0,0 +1,49 @@
+/*
+ * COPYRIGHT LICENSE NOTICE HERE
+ */
+import { Injectable, PLATFORM_ID } from '@angular/core';
+import { isPlatformBrowser } from '@angular/common';
+import { ActivatedRoute } from '@angular/router';
+
+import { Metadata_Page } from 'services/app/Definitions';
+import { Service_Page, METADATA_SITE } from 'services/app/Metadata';
+
+
+
+
+@Injectable({
+ providedIn: 'root',
+})
+export class Data_Page extends Metadata_Page {
+ public constructor(
+ private service: Service_Page,
+ ) {
+ super();
+ }
+
+
+ public Init(route: ActivatedRoute) {
+ // setting functional metadata
+ this.Mode_Browser = isPlatformBrowser(PLATFORM_ID);
+ this.URL = route.snapshot.url.toString();
+ this.Site = METADATA_SITE;
+
+
+ // setting language-specific metadata
+ switch (route.snapshot.data['lang']) {
+ case 'en':
+ case 'en-Latn':
+ default:
+ // English (en)
+ this.Lang = 'en';
+ this.Title = '404';
+ this.Description = 'Page Not Found';
+ this.Keywords = 'website, 404';
+ break;
+ }
+
+
+ // initiate the page
+ this.service.Init(this);
+ }
+}
diff --git a/Angular/contents/404/page.css b/Angular/contents/404/page.css
index 0e6b958a..e69de29b 100644
--- a/Angular/contents/404/page.css
+++ b/Angular/contents/404/page.css
@@ -1,3 +0,0 @@
-/*
- * COPYRIGHT LICENSE NOTICE HERE
- */
diff --git a/Angular/contents/404/page.html b/Angular/contents/404/page.html
index a201fdca..d8220db5 100644
--- a/Angular/contents/404/page.html
+++ b/Angular/contents/404/page.html
@@ -1,8 +1,5 @@
-
-
-