Skip to content

Commit

Permalink
solve #194, #196
Browse files Browse the repository at this point in the history
  • Loading branch information
Ethosa committed Nov 27, 2023
1 parent 4c4cd4c commit c32a52a
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 31 deletions.
2 changes: 1 addition & 1 deletion happyx.nimble
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

description = "Macro-oriented asynchronous web-framework written with ♥"
author = "HapticX"
version = "3.4.0"
version = "3.5.0"
license = "MIT"
srcDir = "src"
installExt = @["nim"]
Expand Down
47 changes: 44 additions & 3 deletions src/happyx/cli/consts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,25 @@ yarn.lock
<body>
You at {{ title }} page ✨
</body>
</html>"""
nimjaPwaTemplate* = """<!DOCTYPE html><html>
<head>
<meta charset="utf-8">
<title>{{ title }}</title>
<link rel="manifest" href="/pwa/manifest.json" />
</head>
<body>
<div>
You at {{ title }} page ✨
</div>
<script>
if ('serviceWorker' in navigator) {{
window.addEventListener('load',()=> {{
navigator.serviceWorker.register('/pwa/service_worker.js');
}});
}}
</script>
</body>
</html>"""
ssrTemplateNinja* = """# Import HappyX
import
Expand All @@ -109,19 +128,41 @@ proc render(title: string): string =
renderTemplate("index.html")
# Serve at http://127.0.0.1:5000
serve("127.0.0.1", 5000):
serve "127.0.0.1", 5000:
# on GET HTTP method at http://127.0.0.1:5000/TEXT
get "/{{title:string}}":
req.answerHtml render(title)
# on any HTTP method at http://127.0.0.1:5000/public/path/to/file.ext
staticDir "public"
"""
ssrTemplatePwaNinja* = """# Import HappyX
import
{imports.join(",\n ")}
# Declare template folder
templateFolder("templates")
proc render(title: string): string =
## Renders template and returns HTML string
##
## `title` is template argument
renderTemplate("index.html")
# Serve at http://127.0.0.1:5000
serve "127.0.0.1", 5000:
# on GET HTTP method at http://127.0.0.1:5000/TEXT
get "/{{title:string}}":
req.answerHtml render(title)
# on any HTTP method at http://127.0.0.1:5000/public/path/to/file.ext
staticDir "public"
staticDir "pwa" ~ "js,json"
"""
ssrTemplate* = """# Import HappyX
import
{imports.join(",\n ")}
# Serve at http://127.0.0.1:5000
serve("127.0.0.1", 5000):
serve "127.0.0.1", 5000:
# on GET HTTP method at http://127.0.0.1:5000/
get "/":
# Return plain text
Expand Down Expand Up @@ -219,7 +260,7 @@ self.addEventListener('install', (event)=> {
"short_name": "{projectName}",
"display": "fullscreen",
"orientation": "portrait",
"start_url": "https://hapticx.github.io/happyx/#/",
"start_url": "https://hapticx.github.io/happyx/",
"icons": [
{{
"src": "https://hapticx.github.io/happyx/public/icon.png",
Expand Down
42 changes: 30 additions & 12 deletions src/happyx/cli/create_command.nim
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ proc createCommand*(name: string = "", kind: string = "", templates: bool = fals
return QuitFailure

if language == "":
if selected > 1:
if selected > 2:
# Only for Nim
echo ""
styledEcho emoji["🐲"](), " You choose project type that allowed only for Nim."
Expand All @@ -132,6 +132,10 @@ proc createCommand*(name: string = "", kind: string = "", templates: bool = fals
styledEcho emoji["🔥"](), " Do you want to use templates in your project? "
selectedTemplates = chooseFrom(templatesList, templatesList)
templates = selectedTemplates == 0
elif projectType == "SSR+PWA":
echo ""
styledEcho emoji["💡"](), " you choose ", fgRed, "SSR + PWA ", fgWhite, "project type so templates was been enabled"
templates = true
elif lang == "nim" and projectType in ["SPA", "HPX", "SPA+PWA"]:
echo ""
styledEcho emoji["🐲"](), " Do you want to use Tailwind CSS in your project? "
Expand Down Expand Up @@ -178,23 +182,37 @@ proc createCommand*(name: string = "", kind: string = "", templates: bool = fals
f.write("import happyx\n\n\npathParams:\n id int\n")
f.close()

let isPwa = selected in {1, 4}
case selected
of 0, 1:
# SSR/SSG
of 0, 1, 2:
# SSR/SSR+PWA/SSG
createDir(projectName / "src" / "public")
if isPwa:
createDir(projectName / "src" / "pwa")
f = open(projectName / "src" / "pwa" / "manifest.json", fmWrite)
f.write(spaPwaManifest)
f.close()
f = open(projectName / "src" / "pwa" / "service_worker.js", fmWrite)
f.write(spaServiceWorkerTemplate)
f.close()
if templates:
styledEcho fgYellow, "Templates in SSR was enabled. To disable it remove --templates flag."
createDir(projectName / "src" / "templates")
f = open(projectName / "src" / "templates" / "index.html", fmWrite)
f.write(nimjaTemplate)
if isPwa:
f.write(nimjaPwaTemplate)
else:
f.write(nimjaTemplate)
f.close()
else:
styledEcho fgYellow, "Templates in SSR was disabled. To enable it add --templates flag."
# Create main file
case lang
of "nim":
f = open(projectName / "src" / fmt"{SPA_MAIN_FILE}.nim", fmWrite)
if templates:
if templates and isPwa:
f.write(fmt(ssrTemplatePwaNinja))
elif templates:
f.write(fmt(ssrTemplateNinja))
else:
f.write(fmt(ssrTemplate))
Expand All @@ -210,7 +228,7 @@ proc createCommand*(name: string = "", kind: string = "", templates: bool = fals
f.write(tsTemplate)
makeTsPackageJson(projectName)
f.close()
of 2, 3:
of 3, 4:
# SPA + PWA
imports.add("components/[hello_world]")
createDir(projectName / "src" / "public")
Expand All @@ -222,12 +240,12 @@ proc createCommand*(name: string = "", kind: string = "", templates: bool = fals
var additionalHead = ""
if useTailwind:
additionalHead &= "<script src=\"https://cdn.tailwindcss.com\"></script>\n "
if selected == 2:
f.write(fmt(spaIndexTemplate))
elif selected == 3:
if isPwa:
f.write(fmt(spaPwaIndexTemplate))
else:
f.write(fmt(spaIndexTemplate))
f.close()
if selected == 3:
if isPwa:
f = open(projectName / "src" / "service_worker.js", fmWrite)
f.write(spaServiceWorkerTemplate)
f.close()
Expand All @@ -237,7 +255,7 @@ proc createCommand*(name: string = "", kind: string = "", templates: bool = fals
f = open(projectName / "src" / "components" / "hello_world.nim", fmWrite)
f.write(componentTemplate)
f.close()
of 4:
of 5:
# HPX
createDir(projectName / "src" / "public")
createDir(projectName / "src" / "components")
Expand All @@ -260,7 +278,7 @@ proc createCommand*(name: string = "", kind: string = "", templates: bool = fals
discard
eraseLine(stdout)
cursorUp(stdout)
styledEcho "✨ Project initialized "
styledEcho "✨ Project initialized ", " ".repeat(24)

# Tell user about choosen
styledEcho fgYellow, emoji["🐥"](), " You choose ", fgMagenta, programmingLanguagesDesc[selectedLang], fgYellow, " programming language for this project."
Expand Down
19 changes: 7 additions & 12 deletions src/happyx/cli/utils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type
ptSPA = "SPA",
ptSPA_PWA = "SPA+PWA",
ptSSG = "SSG",
ptSSR_PWA = "SSR+PWA",
ptSSR = "SSR",
ptSPAHpx = "HPX"
ProgrammingLanguage* {.pure, size: sizeof(int8).} = enum
Expand Down Expand Up @@ -77,10 +78,10 @@ const


var
projectTypes*: array[5, string]
projectTypes*: array[6, string]
tailwindList*: array[2, string]
templatesList*: array[2, string]
projectTypesDesc*: array[5, string]
projectTypesDesc*: array[6, string]
programmingLanguages*: array[4, string]
programmingLanguagesDesc*: array[4, string]

Expand Down Expand Up @@ -117,6 +118,7 @@ var
proc init*() =
projectTypes = [
"SSR",
"SSR+PWA",
"SSG",
"SPA",
"SPA+PWA",
Expand All @@ -132,6 +134,7 @@ proc init*() =
]
projectTypesDesc = [
ansiStyleCode(styleBright) & ansiForegroundColorCode(fgGreen) & "Server-side rendering " & emoji[""]() & ansiResetCode,
ansiStyleCode(styleBright) & ansiForegroundColorCode(fgGreen) & "Server-side rendering with PWA " & emoji[""]() & ansiResetCode,
ansiStyleCode(styleBright) & ansiForegroundColorCode(fgBlue) & "Static site generation " & emoji["📦"]() & ansiResetCode,
ansiStyleCode(styleBright) & ansiForegroundColorCode(fgYellow) & "Single-page application " & emoji[""]() & ansiResetCode,
ansiStyleCode(styleBright) & ansiForegroundColorCode(fgYellow) & "Single-page application with PWA " & emoji[""]() & ansiResetCode,
Expand Down Expand Up @@ -211,15 +214,7 @@ proc compileProject*(): ProjectData {. discardable .} =
result = readConfig()

case result.projectType:
of ptSPA:
result.process = startProcess(
"nim", getCurrentDir() / result.srcDir,
[
"js", "-c", "--hints:off", "--warnings:off",
"--opt:size", "-d:danger", "-x:off", "-a:off", "--panics:off", "--lineDir:off", result.mainFile
], nil, PROCESS_OPTIONS
)
of ptSPA_PWA:
of ptSPA, ptSPA_PWA:
result.process = startProcess(
"nim", getCurrentDir() / result.srcDir,
[
Expand Down Expand Up @@ -318,7 +313,7 @@ proc compileProject*(): ProjectData {. discardable .} =
"--opt:size", "-d:danger", "-x:off", "-a:off", "--panics:off", "--lineDir:off", result.mainFile
], nil, PROCESS_OPTIONS
)
of ptSSR, ptSSG:
of ptSSR, ptSSG, ptSSR_PWA:
return result

styledEcho "Compiling ", fgMagenta, result.mainFile, fgWhite, " script ... /"
Expand Down
2 changes: 1 addition & 1 deletion src/happyx/core/constants.nim
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ const
nim_2_0_0* = (NimMajor, NimMinor, NimPatch) >= (2, 0, 0)
# Framework version
HpxMajor* = 3
HpxMinor* = 4
HpxMinor* = 5
HpxPatch* = 0
HpxVersion* = $HpxMajor & "." & $HpxMinor & "." & $HpxPatch

Expand Down
12 changes: 10 additions & 2 deletions src/happyx/private/macro_utils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,7 @@ proc buildHtmlProcedure*(root, body: NimNode, inComponent: bool = false,
result = newCall("initTag", elementName)

for statement in body:
echo treeRepr statement
if statement.kind == nnkDiscardStmt:
continue
elif statement.kind == nnkPrefix and statement[0] == ident"!" and statement[1] == ident"debugRoot":
Expand Down Expand Up @@ -932,8 +933,15 @@ proc buildHtmlProcedure*(root, body: NimNode, inComponent: bool = false,
result.add(newCall("tag", newLit(getTagName($statement[0]))))

elif statement.kind == nnkCurly and statement.len == 1:
# variables
result.add(newCall("initTag", newCall("$", statement[0]), newLit(true)))
# variables and procedures
result.add(newNimNode(nnkWhenStmt).add(newNimNode(nnkElifBranch).add(
newCall(
"is", statement[0], ident"TagRef"
),
statement[0]
), newNimNode(nnkElse).add(
newCall("initTag", newCall("$", statement[0]), newLit(true))
)))

# if-elif or case-of
elif statement.kind in [nnkCaseStmt, nnkIfStmt, nnkIfExpr, nnkWhenStmt]:
Expand Down
15 changes: 15 additions & 0 deletions tests/testjs15.nim
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ component withSlot:
slot


proc titleTag(title: string): TagRef =
buildHtml:
tTitle: {title}


component Exam:
`template`:
tDiv:
Expand Down Expand Up @@ -111,3 +116,13 @@ appRoutes("app"):
withSlot(): "one"
#tDiv:
#withSlot($7): "seven"

"/issue194":
var fruits = buildHtml:
"banana"
"apple"
"mango"
buildHtml:
{titleTag("Hello")}
for i in 0..<10:
{fruits.children[0]}

0 comments on commit c32a52a

Please sign in to comment.