@awesomeness-js/server 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +61 -0
  2. package/build/build.js +7 -0
  3. package/build/postBuild.js +7 -0
  4. package/example-.awesomeness/componentLocations.js +15 -0
  5. package/example-.awesomeness/config.js +5 -21
  6. package/example-site/example.awesomenessjs.com/api/readme.md +1 -0
  7. package/example-site/example.awesomenessjs.com/components/example/index.js +3 -0
  8. package/example-site/example.awesomenessjs.com/components/notCommonExample/_.css +1 -0
  9. package/example-site/example.awesomenessjs.com/components/notCommonExample/index.js +3 -0
  10. package/example-site/example.awesomenessjs.com/pages/_md/_info.js +15 -0
  11. package/example-site/example.awesomenessjs.com/pages/_md/css/example.css +4 -0
  12. package/example-site/example.awesomenessjs.com/pages/_md/drafts/example.md +32 -0
  13. package/example-site/example.awesomenessjs.com/pages/_md/getBlogData.js +117 -0
  14. package/example-site/example.awesomenessjs.com/pages/_md/getData.js +36 -0
  15. package/example-site/example.awesomenessjs.com/pages/_md/js/callToAction.js +43 -0
  16. package/example-site/example.awesomenessjs.com/pages/_md/js/init.js +88 -0
  17. package/example-site/example.awesomenessjs.com/pages/_md/meta.template.md +33 -0
  18. package/example-site/example.awesomenessjs.com/pages/_md/pages/mission.md +345 -0
  19. package/example-site/example.awesomenessjs.com/pages/_template/_info.js +9 -0
  20. package/example-site/example.awesomenessjs.com/pages/_template/css/_.css +4 -0
  21. package/example-site/example.awesomenessjs.com/pages/_template/getData.js +6 -0
  22. package/example-site/example.awesomenessjs.com/pages/_template/js/init.js +3 -0
  23. package/example-site/example.awesomenessjs.com/pages/blog/_info.js +14 -0
  24. package/example-site/example.awesomenessjs.com/pages/blog/css/topics.css +17 -0
  25. package/example-site/example.awesomenessjs.com/pages/blog/getData.js +22 -0
  26. package/example-site/example.awesomenessjs.com/pages/blog/js/colors.js +159 -0
  27. package/example-site/example.awesomenessjs.com/pages/blog/js/init.js +242 -0
  28. package/example-site/example.awesomenessjs.com/pages/blog/js/tag.js +111 -0
  29. package/example-site/example.awesomenessjs.com/pages/examples/_info.js +9 -0
  30. package/example-site/example.awesomenessjs.com/pages/examples/css/footer.css +6 -0
  31. package/example-site/example.awesomenessjs.com/pages/examples/css/intro.css +67 -0
  32. package/example-site/example.awesomenessjs.com/pages/examples/css/nav.css +221 -0
  33. package/example-site/example.awesomenessjs.com/pages/examples/getData.js +8 -0
  34. package/example-site/example.awesomenessjs.com/pages/examples/js/init.js +15 -0
  35. package/example-site/example.awesomenessjs.com/pages/examples/js/updateState.js +14 -0
  36. package/example-site/example.awesomenessjs.com/pages/start/_info.js +11 -0
  37. package/example-site/example.awesomenessjs.com/pages/start/css/footer.css +6 -0
  38. package/example-site/example.awesomenessjs.com/pages/start/css/intro.css +67 -0
  39. package/example-site/example.awesomenessjs.com/pages/start/css/nav.css +221 -0
  40. package/example-site/example.awesomenessjs.com/pages/start/getData.js +8 -0
  41. package/example-site/example.awesomenessjs.com/pages/start/js/init.js +30 -0
  42. package/example-site/example.awesomenessjs.com/pages/start/js/updateState.js +14 -0
  43. package/example-site/example.awesomenessjs.com/public/images/awesomeness.webp +0 -0
  44. package/example-site/example.awesomenessjs.com/public/manifest.webmanifest.json +8 -0
  45. package/example-site/example.awesomenessjs.com/specialRoutes.js +14 -0
  46. package/index.js +105 -25
  47. package/package.json +5 -2
  48. package/{server → src}/applicationMap.js +1 -1
  49. package/{server → src}/awesomenessNormalizeRequest.js +24 -3
  50. package/{server → src}/componentDependencies.js +11 -5
  51. package/{config.js → src/config.js} +6 -1
  52. package/{server → src}/fetchPage.js +6 -6
  53. package/src/getConfig.js +3 -0
  54. package/src/init.js +3 -0
  55. package/{server → src}/koa/attachAwesomenessRequest.js +5 -6
  56. package/{server → src}/koa/cors.js +2 -4
  57. package/{server → src}/koa/errorHandler.js +3 -3
  58. package/{server → src}/koa/finalFormat.js +2 -5
  59. package/{server → src}/koa/jsonBodyParser.js +3 -3
  60. package/src/koa/routeRequest.js +334 -0
  61. package/{server → src}/koa/serverUp.js +2 -4
  62. package/{server → src}/koa/staticFiles.js +10 -11
  63. package/{server → src}/koa/timeout.js +3 -3
  64. package/{server → src}/pageInfo.js +6 -6
  65. package/{server → src}/reRoute.js +3 -2
  66. package/{server → src}/resolveRealCasePath.js +1 -1
  67. package/{start.js → src/start.js} +14 -13
  68. package/{server → src}/validateRequest.js +1 -1
  69. package/{server → src}/ws/handlers.js +4 -2
  70. package/{server → src}/ws/index.js +2 -2
  71. package/ui/README.md +438 -0
  72. package/ui/awesomeness-ui.instructions.md +156 -0
  73. package/ui/build.js +119 -0
  74. package/ui/commonComponent.test.js +27 -0
  75. package/ui/components/blogPost/all.css +371 -0
  76. package/ui/components/blogPost/headerImage.js +153 -0
  77. package/ui/components/blogPost/index.js +45 -0
  78. package/ui/components/blogPost/marked.js +74 -0
  79. package/ui/components/blogPost/md.js +73 -0
  80. package/ui/components/blogPost/parseAwesomeness.jQuery.js +47 -0
  81. package/ui/components/blogPost/readme.md +8 -0
  82. package/ui/components/colors/README.md +65 -0
  83. package/ui/components/colors/dynamic.css +1884 -0
  84. package/ui/components/colors/dynamic.css.js +135 -0
  85. package/ui/components/colors/dynamic.css.php +79 -0
  86. package/ui/components/colors/example.js +133 -0
  87. package/ui/components/colors/index.js +65 -0
  88. package/ui/components/colors/map.js +13 -0
  89. package/ui/components/colors/random.js +17 -0
  90. package/ui/components/colors/tailwind-colors.css +247 -0
  91. package/ui/components/insertIntoList/insertIntoList.jquery.js +150 -0
  92. package/ui/components/tag/category.js +8 -0
  93. package/ui/components/tag/index.js +33 -0
  94. package/ui/components/tag/list.js +42 -0
  95. package/ui/components/tag/map.js +64 -0
  96. package/ui/components/tag/tagMap.css +60 -0
  97. package/ui/components/tag/tags.css +20 -0
  98. package/ui/core/css/_normalize.css +57 -0
  99. package/ui/core/css/dynamic/flex.js +36 -0
  100. package/ui/core/css/dynamic/grid.js +185 -0
  101. package/ui/core/css/dynamic/shortcuts.js +48 -0
  102. package/ui/core/css/dynamic/spacing.js +61 -0
  103. package/ui/core/css/dynamic/text.js +80 -0
  104. package/ui/core/css/dynamic/width.js +75 -0
  105. package/ui/core/css/dynamic.js +40 -0
  106. package/ui/core/js/app/api.js +143 -0
  107. package/ui/core/js/app/init.js +88 -0
  108. package/ui/core/js/app/initDarkMode.js +26 -0
  109. package/ui/core/js/app/initialScroll.js +28 -0
  110. package/ui/core/js/app/meta/update/components.js +65 -0
  111. package/ui/core/js/app/meta/update/pages.js +86 -0
  112. package/ui/core/js/app/metaUpdates.js +10 -0
  113. package/ui/core/js/app/page.js +319 -0
  114. package/ui/core/js/app/resize.js +52 -0
  115. package/ui/core/js/app/state/back.js +16 -0
  116. package/ui/core/js/app/state/create.js +50 -0
  117. package/ui/core/js/app/state/get.js +5 -0
  118. package/ui/core/js/app/state/init.js +25 -0
  119. package/ui/core/js/app.js +41 -0
  120. package/ui/core/js/jquery-3.7.1.min.js +2 -0
  121. package/ui/core/public/app.css +1 -0
  122. package/ui/core/public/app.js +975 -0
  123. package/ui/core/public/favicon.ico +0 -0
  124. package/ui/core/public/index.html +40 -0
  125. package/server/koa/routeRequest.js +0 -286
  126. /package/{server/errors.js → errors.js} +0 -0
  127. /package/{server → src}/brotliJsonResponse.js +0 -0
  128. /package/{server → src}/checkAccess.js +0 -0
  129. /package/{server → src}/getMD.js +0 -0
  130. /package/{server → src}/specialPaths.js +0 -0
package/README.md CHANGED
@@ -8,6 +8,67 @@ The `./awesomeness/` folder and you can customize the location by modifying the
8
8
 
9
9
  [@awesomeness-js/app-template](https://github.com/awesomeness-js/app-template)
10
10
 
11
+ # Underlying Request Flow
12
+
13
+ ## Pre Routing
14
+ - start
15
+ - attachAwesomenessRequest
16
+ - gets awesomenessRequest.awesomenessType [page, api, generic]
17
+ - [staticFiles](#Static-Files)
18
+ - beforeRouteMiddleware
19
+ - routeRequest
20
+
21
+ ## Routing
22
+ - needs to be valid route for [page, api]
23
+ - /[^a-zA-Z0-9\/\_\-]/ -> make sure there is no dots in the path -> 404
24
+
25
+ ## API Routing ( needs awesomenessType in post body `api`)
26
+ - try /api/routes/${awesomenessRequest.pageRoute}
27
+ - try site specific first
28
+ - then try common routes (needs to be edited uses URL and not passed config)
29
+ - validateRequest
30
+ - route index.js
31
+
32
+ ## Page Routing ( needs awesomenessType in post body `page`)
33
+ - pageInfo
34
+ - validateRequest
35
+ - fetchPage
36
+ - finalFormat
37
+
38
+ ## Generic Routing ( has no defined awesomenessType in post body)
39
+ - method must be get or 405 is thrown
40
+ - /test -> returns awesomeness is working
41
+ - routes to staticFiles
42
+ - awesomenessRequest.awesomenessType is not set in POST body
43
+ - request is treated as a static file request
44
+ - static file served is it exists in the public folder
45
+ - site specific first
46
+ - then common files
47
+
48
+ If a public static file is not found
49
+ - public/index.html is served
50
+ - You DO NOT need your own public/index.html file
51
+ - The awesomeness-ui framework provides a default one
52
+ - this calls app.init()
53
+
54
+ # From the Browser
55
+
56
+ ## What happens
57
+
58
+ 1. User visits a page
59
+ - Server receives request
60
+
61
+
62
+ ## Static Files
63
+ - site specific files first
64
+ - /${awesomenessConfig.siteDir__URL}/${awesomenessRequest.site}/public/index.html
65
+ - then common files
66
+ - [/${awesomenessConfig.commonPublicDir__URL}/${awesomenessRequest.site}/public/index.html](/example-site/example.awesomenessjs.com/public/index.html)
67
+
68
+ [index.html](/example-site/example.awesomenessjs.com/public/index.html)
69
+
70
+
71
+
11
72
  ## License
12
73
 
13
74
  This project is licensed under the Apache License 2.0.
package/build/build.js ADDED
@@ -0,0 +1,7 @@
1
+ import { build } from '@awesomeness-js/utils';
2
+
3
+ build({
4
+ src: './src',
5
+ dest: './index.js',
6
+ dts: false
7
+ });
@@ -0,0 +1,7 @@
1
+ import { build } from '@awesomeness-js/utils';
2
+
3
+ build({
4
+ src: './src',
5
+ dest: './types/index.d.ts',
6
+ dts: true
7
+ });
@@ -0,0 +1,15 @@
1
+ export default (awesomenessRequest) => {
2
+
3
+ const siteSpecific__URL = new URL(`../sites/${awesomenessRequest.site}/`, import.meta.url);
4
+
5
+ return [
6
+
7
+ // first match wins (site first)
8
+ new URL('./components/', siteSpecific__URL),
9
+
10
+ // last item is the default
11
+ new URL('../awesomeness-ui/components/', import.meta.url),
12
+
13
+ ];
14
+
15
+ };
@@ -5,31 +5,15 @@ import wsHandler from './wsHandler.js';
5
5
  import beforeRouteMiddleware from './beforeRouteMiddleware.js';
6
6
  import checkSession from './checkSession.js';
7
7
  import applicationMap from './applicationMap.js';
8
+ import componentLocations from './componentLocations.js';
8
9
 
9
10
  export default {
10
-
11
- configURL: new URL(import.meta.url),
12
- siteURL: new URL("../sites/", import.meta.url),
13
- commonPublicDir: new URL("../awesomeness-ui/core/public/", import.meta.url),
14
-
15
- componentLocations: (awesomenessRequest) => {
16
-
17
- const siteURL = new URL(`../sites/${awesomenessRequest.site}/`, import.meta.url);
18
-
19
- return [
20
-
21
- // first match wins (site first)
22
- new URL('./components/', siteURL),
23
-
24
- // last item is the default
25
- new URL('../awesomeness-ui/components/', import.meta.url),
26
- ];
27
-
28
- },
29
-
11
+ siteDir__URL: new URL("../sites/", import.meta.url),
12
+ commonPublicDir__URL: new URL("../awesomeness-ui/core/public/", import.meta.url),
13
+ commonApiDir__URL: new URL("../api/", import.meta.url),
14
+ componentLocations,
30
15
  debug: true,
31
16
  byPassAccessRequirementsInDev: true,
32
-
33
17
  applicationMap,
34
18
  beforeRouteMiddleware,
35
19
  checkSession,
@@ -0,0 +1 @@
1
+ custom routes can be added here.
@@ -0,0 +1,3 @@
1
+ export default () => {
2
+ console.log('This example component over-wrote the common example component');
3
+ }
@@ -0,0 +1,3 @@
1
+ export default () => {
2
+ console.log('This is not a common example');
3
+ }
@@ -0,0 +1,15 @@
1
+ export default {
2
+ version: 1,
3
+ name: '',
4
+ description: 'this allows for any url to be treated as a blog post, if the slug matches a blog post, all post are simple md format',
5
+ permissions: [ '*' ],
6
+ components: [
7
+ 'blogPage',
8
+ 'blogPost',
9
+ 'prism',
10
+ 'statusPage',
11
+ 'video',
12
+ 'riskDisclosure',
13
+ 'bibleVerse'
14
+ ]
15
+ };
@@ -0,0 +1,4 @@
1
+ /*
2
+ these classes are loaded dynamically ...
3
+ If a class can be re-used it is better to be created in /api/ui/common-css/
4
+ */
@@ -0,0 +1,32 @@
1
+ ---
2
+ title: Example Post
3
+ subTitle: This post wont show up because its in drafts.
4
+ image: /tools/images/posts/investing-101.webp
5
+ published: 2025-10-10
6
+ priority: null
7
+ url: /test-post
8
+ tags: [ faith, life hacks, spiritual freedom, christianity ]
9
+ tagColor: bg-stone-900
10
+ author:
11
+ name: Scott Forte
12
+ title: Pilot, Investor, Realtor ®
13
+ image: /tools/images/scott-forte-america-small-40.webp
14
+ url: https://scottmforte.com
15
+ ---
16
+
17
+ <break-50>
18
+
19
+ <youTube>ek_RodYzUCI</youTube>
20
+
21
+ ![](/tools/images/posts/c172-glide-distance.webp)
22
+
23
+ <div class="blogPost-next-reads">
24
+
25
+ ### Next Reads
26
+
27
+ - [Investing 101: Planting a Money Tree](/investing-101)
28
+ - [🏔️ Moving to NH: The Freest State on Planet Earth](/moving-to-new-hampshire)
29
+ - [Alternative Investments: Beyond Stocks, bonds, 401ks and IRAs](/alternative-investments)
30
+ - [👨‍✈️ Spiritual Freedom: When Jesus Becomes Your Co-Pilot](/spiritual-freedom)
31
+
32
+ </div>
@@ -0,0 +1,117 @@
1
+ import fs from 'fs';
2
+ import parseMd from '#utils/parseMd.js';
3
+ import path from 'path';
4
+ import { fileURLToPath } from 'url';
5
+
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = path.dirname(__filename);
8
+
9
+ function tagToFilename(tag) {
10
+
11
+ return tag.toLowerCase().replace(/\s+/g, '-').replace(/[^\w-]/g, '');
12
+
13
+ }
14
+
15
+ export default async function getBlogData(folder = 'pages') {
16
+
17
+ const folderPath = path.resolve(__dirname, folder);
18
+ const files = fs.readdirSync(folderPath).filter((f) => f.endsWith('.md'));
19
+
20
+ const tagImagePath = path.resolve(__dirname, '../../public/tools/images/tags');
21
+ const tagImageFiles = fs.existsSync(tagImagePath) ? fs.readdirSync(tagImagePath) : [];
22
+
23
+ const tagMap = Object.create(null);
24
+
25
+
26
+ const result = {
27
+ tags: [], // now array of { name, count }
28
+ links: [], // array of urls
29
+ posts: [] // array of metadata objects
30
+ };
31
+
32
+ const linkRegex = /\[([^\]]+)\]\(([^)\s]+)\)/g;
33
+
34
+ for (const file of files) {
35
+
36
+ try {
37
+
38
+ const filePath = path.join(folderPath, file);
39
+ const mdContent = fs.readFileSync(filePath, 'utf-8');
40
+
41
+ const {
42
+ metadata,
43
+ cleanedMDContent
44
+ } = await parseMd(mdContent);
45
+
46
+ if (!metadata || !metadata.published) continue;
47
+
48
+ // collect tags
49
+ if (Array.isArray(metadata.tags)) {
50
+
51
+ for (const tag of metadata.tags) {
52
+
53
+ if (!tag) continue;
54
+ tagMap[tag] = (tagMap[tag] || 0) + 1;
55
+
56
+ }
57
+
58
+ }
59
+
60
+ // collect links
61
+ let match;
62
+
63
+
64
+ while ((match = linkRegex.exec(cleanedMDContent)) !== null) {
65
+
66
+ const url = match[2];
67
+
68
+ result.links.push(url);
69
+
70
+ }
71
+
72
+ // collect post metadata
73
+ result.posts.push({
74
+ file,
75
+ ...metadata
76
+ });
77
+
78
+ } catch(err){
79
+
80
+ console.error(`Error processing file ${file}:`, err);
81
+
82
+ }
83
+
84
+
85
+
86
+ }
87
+
88
+ // build tag array
89
+ result.tags = Object.entries(tagMap)
90
+ .map(([ name, count ]) => ({
91
+ name,
92
+ count,
93
+ image: tagImageFiles.includes(tagToFilename(name) + '.webp') ? `/tools/images/tags/${tagToFilename(name)}.webp` : null
94
+ }))
95
+ .sort((a, b) => a.name.localeCompare(b.name));
96
+
97
+ // sort posts by priority (asc), then date (desc), fallback to title
98
+ result.posts.sort((a, b) => {
99
+
100
+ const ap = (typeof a.priority === 'number') ? a.priority : Infinity;
101
+ const bp = (typeof b.priority === 'number') ? b.priority : Infinity;
102
+
103
+ if (ap !== bp) return ap - bp;
104
+
105
+ const ad = new Date(a.published);
106
+ const bd = new Date(b.published);
107
+
108
+ if (!isNaN(ad) && !isNaN(bd)) return bd - ad;
109
+
110
+ return (a.title || '').localeCompare(b.title || '');
111
+
112
+ });
113
+
114
+
115
+ return result;
116
+
117
+ }
@@ -0,0 +1,36 @@
1
+ import parseMd from '#utils/parseMd.js';
2
+ import checkAccess from '#server/checkAccess.js';
3
+
4
+ // @awesomenessRequest
5
+ export default async function getData(awesomenessRequest) {
6
+
7
+ let mdContent =
8
+ awesomenessRequest.mdContent
9
+ || awesomenessRequest.data.mdContent
10
+ || '## No Content Found\n\nSorry, no content could be found for this post.';
11
+
12
+ let {
13
+ metadata,
14
+ cleanedMDContent,
15
+ } = await parseMd(mdContent);
16
+
17
+ mdContent = cleanedMDContent;
18
+
19
+ awesomenessRequest.pageInit = '_md';
20
+
21
+ // check permissions?
22
+ if(metadata?.permissions?.length){
23
+
24
+ await checkAccess({
25
+ permissionsAllowed: metadata.permissions,
26
+ awesomenessRequest,
27
+ });
28
+
29
+ }
30
+
31
+ return {
32
+ mdContent,
33
+ metadata,
34
+ };
35
+
36
+ }
@@ -0,0 +1,43 @@
1
+ import ui from '#ui';
2
+
3
+ app.pages._md.callToAction = async function(){
4
+
5
+ $(`.custom-callToAction-real-estate`).each(function(){
6
+
7
+ const $container = $(this);
8
+
9
+ $container.empty();
10
+
11
+ const $break = $(`<div class="break height-100"></div>`)
12
+ .appendTo($container);
13
+
14
+ const $h1 = $(`<h1 class="">Ready to start investing?</h1>`)
15
+ .appendTo($container);
16
+
17
+ const $break2 = $(`<div class="break height-25"></div>`)
18
+ .appendTo($container);
19
+
20
+ const $p = $(`<p class="lead">
21
+ I turn down about 200 deals a year <b>because I do the math</b>.
22
+ They simply don't pencil out.
23
+ I also have an extremely conservative investment criteria.
24
+ That said,
25
+ Ive flipped over 40 units
26
+ from single family homes,
27
+ to office condos and hotels.
28
+ I currently own over 150 units.
29
+ You need me, or someone like me, as your copilot.
30
+ If you are interested in learning more about investment real estate,
31
+ no matter where in the world you live,
32
+ text me
33
+ </p>`).appendTo($container);
34
+
35
+ const $link = $(`<a href="sms:855.SCOTT.40" class="">855.SCOTT.40</a>`)
36
+ .appendTo($p);
37
+
38
+ const $break3 = $(`<div class="break height-100"></div>`)
39
+ .appendTo($container);
40
+
41
+ });
42
+
43
+ };
@@ -0,0 +1,88 @@
1
+ import ui from '#ui';
2
+
3
+ app.pages._md.init = async function(pageData){
4
+
5
+ ui.cleanMain();
6
+
7
+ if(
8
+ pageData.metadata.breadcrumbs
9
+ && !pageData.metadata.image
10
+ ){
11
+
12
+ ui.breadcrumbs({
13
+ data: pageData.metadata.breadcrumbs,
14
+ color: pageData.metadata.breadcrumbColor ?? 'stone'
15
+ }).appendTo(app.$main);
16
+
17
+ }
18
+
19
+ const $page = ui.blogPost.md(pageData,{
20
+ tagBase: '/tag',
21
+ customRules: [
22
+ (mdContent)=>{
23
+
24
+ return mdContent.replace(/<cta-realEstate>/g, '<div class="custom-callToAction-real-estate"></div>');
25
+
26
+ },
27
+ (mdContent)=>{
28
+
29
+ // find <bibleVerse> tags and replace with divs
30
+ return mdContent.replace(/<bibleVerse>/g, '<div class="data-bible-verse">').replace(/<\/bibleVerse>/g, '</div>');
31
+
32
+ }
33
+ ]
34
+ }).appendTo(app.$main);
35
+
36
+ $page.find('a').click(function(event){
37
+
38
+ event.preventDefault();
39
+ event.stopPropagation();
40
+
41
+ const href = $(this).attr('href');
42
+
43
+ if(href && href.startsWith('http')){
44
+
45
+ // open target blank
46
+ window.open(href, '_blank');
47
+
48
+ } else {
49
+
50
+ // does this a tag have any awesomeness-* class
51
+ if($(this).attr('class') && $(this).attr('class').match(/awesomeness-/)){
52
+
53
+ // do nothing, let awesomeness-ui handle it
54
+
55
+ } else {
56
+
57
+ // internal links
58
+ app.page(href);
59
+
60
+ }
61
+
62
+ }
63
+
64
+ });
65
+
66
+ // find code blocks that have only a string inside and add class .simple-code-string
67
+ $page.find('code').each(function(){
68
+
69
+ const $code = $(this);
70
+ const codeText = $code.text().trim();
71
+
72
+
73
+ if(codeText && !codeText.includes('\n')){
74
+
75
+ $code.addClass('simple-code-string');
76
+
77
+ }
78
+
79
+ });
80
+
81
+ Prism.highlightAll();
82
+
83
+ app.pages._md.callToAction();
84
+
85
+ ui.bibleVerse.init();
86
+
87
+
88
+ };
@@ -0,0 +1,33 @@
1
+ ---
2
+ title: Some Example Blog Post
3
+ subTitle: This is a subtitle of a blog post
4
+ readTime: null
5
+ image: /tools/images/posts/investing-101.png
6
+ published: 2025-10-10
7
+ priority: null
8
+ url: /test-post
9
+ tags: [ faith, life hacks, spiritual freedom, christianity ]
10
+ tagColor: bg-stone-900
11
+ author:
12
+ name: Scott Forte
13
+ title: Pilot, Investor, Realtor ®
14
+ image: /tools/images/scott-forte-america-small-40.webp
15
+ url: https://scottmforte.com
16
+ ---
17
+
18
+ <break-50>
19
+
20
+ <youTube>5guXs-675KI</youTube>
21
+
22
+ ![](/tools/images/posts/c172-glide-distance.webp)
23
+
24
+ <div class="blogPost-next-reads">
25
+
26
+ ### Next Reads
27
+
28
+ - [👨‍✈️ Spiritual Freedom: When Jesus Becomes Your Co-Pilot](/spiritual-freedom)
29
+ - [💸 Financial Freedom: What does it mean?](/financial-freedom)
30
+ - [🗽 Political Freedom](/political-freedom)
31
+ - [🧠 Mental Freedom: The Basis of Freedom](/mental-freedom)
32
+
33
+ </div>