diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 5e6c415..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,31 +0,0 @@ -# This is a basic workflow to help you get started with Actions - -name: CI - -# Controls when the action will run. -on: - # Triggers the workflow on push or pull request events but only for the master branch - push: - branches: [ master ] - pull_request: - branches: [ master ] - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - # This workflow contains a single job called "build" - build: - # The type of runner that the job will run on - runs-on: ubuntu-latest - container: nimlang/nim - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v2 - # Runs a single command using the runners shell - - name: Tests - run: | - nimble develop -y - nim c -r tests/tester.nim diff --git a/.gitignore b/.gitignore index 842e140..67d9b34 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1 @@ nimcache/ -/tests/tester -karax/tools/karun -*.code-workspace -*.exe -app.js -app.html diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index ac49796..0000000 --- a/LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2017 Xored Software, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/docs/docs.rst b/docs/docs.rst index 3eec1a4..8298ba9 100644 --- a/docs/docs.rst +++ b/docs/docs.rst @@ -10,17 +10,17 @@ and some extensions that allow for an efficient component system. These extensions are: ``VNodeKind.int`` - The node has a single integer field. + The node havs a single integer field. ``VNodeKind.bool`` The node has a single boolean field. -``VNodeKind.vthunk`` +``VNodeKint.vthunk`` The node is a `virtual thunk`:idx:. This means there is a function attached to it that produces the ``VNode`` structure on demand. -``VNodeKind.dthunk`` +``VNodeKint.dthunk`` The node is a `DOM thunk`:idx:. This means there is a function attached to it that produces the ``Node`` DOM structure on demand. @@ -53,6 +53,6 @@ Event system Karax does not abstract over the event system the DOM offers much: The same ``Event`` structure is used. Every callback has the -signature ``proc (ev: Event; n: VNode)`` or empty ``proc ()``. +signature ``proc (ev: Event; n: VNode)``. diff --git a/examples/button.nim b/examples/button.nim deleted file mode 100644 index d86fa82..0000000 --- a/examples/button.nim +++ /dev/null @@ -1,15 +0,0 @@ -include karax / prelude - -var lines: seq[kstring] = @[] - -proc createDom(): VNode = - result = buildHtml(tdiv): - button: - text "Say hello!" - proc onclick(ev: Event; n: VNode) = - lines.add "Hello simulated universe" - for x in lines: - tdiv: - text x - -setRenderer createDom diff --git a/examples/buttonlambda.nim b/examples/buttonlambda.nim deleted file mode 100644 index 2ddadff..0000000 --- a/examples/buttonlambda.nim +++ /dev/null @@ -1,14 +0,0 @@ -include karax / prelude -from future import `=>` - -var lines: seq[kstring] = @[] - -proc createDom(): VNode = - result = buildHtml(tdiv): - button(onclick = () => lines.add "Hello simulated universe"): - text "Say hello!" - for x in lines: - tdiv: - text x - -setRenderer createDom diff --git a/examples/carousel/carousel.html b/examples/carousel/carousel.html deleted file mode 100644 index 500e73a..0000000 --- a/examples/carousel/carousel.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - Carousel app - - - - -
- - - - - diff --git a/examples/carousel/carousel.nim b/examples/carousel/carousel.nim deleted file mode 100644 index c2db56c..0000000 --- a/examples/carousel/carousel.nim +++ /dev/null @@ -1,69 +0,0 @@ -## This demo shows how you can develop your own stateful components with Karax. - -import vdom, vstyles, karax, karaxdsl, jdict, jstrutils, kdom - -type - Carousel = ref object of VComponent - counter: int - cntdown: int - timer: TimeOut - list: seq[cstring] - -const ticksUntilChange = 5 - -var - images: seq[cstring] = @[cstring"a", "b", "c", "d"] - -proc render(x: VComponent): VNode = - let self = Carousel(x) - - proc docount() = - dec self.cntdown - if self.cntdown == 0: - self.counter = (self.counter + 1) mod self.list.len - self.cntdown = ticksUntilChange - else: - self.timer = setTimeout(docount, 30) - markDirty(self) - redraw() - - proc onclick(ev: Event; n: VNode) = - if self.timer != nil: - clearTimeout(self.timer) - self.timer = setTimeout(docount, 30) - - let col = - case self.counter - of 0: cstring"#4d4d4d" - of 1: cstring"#ff00ff" - of 2: cstring"#00ffff" - of 3: cstring"#ffff00" - else: cstring"red" - result = buildHtml(tdiv()): - text self.list[self.counter] - button(onclick = onclick): - text "Next" - tdiv(style = style(StyleAttr.color, col)): - text "This changes its color." - if self.cntdown != ticksUntilChange: - text &self.cntdown - -proc carousel(): Carousel = - result = newComponent(Carousel, render) - result.list = images - result.cntdown = ticksUntilChange - -proc createDom(): VNode = - result = buildHtml(table): - tr: - td: - carousel() - td: - carousel() - tr: - td: - carousel() - td: - carousel() - -setRenderer createDom diff --git a/examples/carousel/carousel.nims b/examples/carousel/carousel.nims deleted file mode 100644 index cef2dec..0000000 --- a/examples/carousel/carousel.nims +++ /dev/null @@ -1 +0,0 @@ ---path: "../../karax" diff --git a/examples/config.nims b/examples/config.nims deleted file mode 100644 index 76ed4d9..0000000 --- a/examples/config.nims +++ /dev/null @@ -1 +0,0 @@ ---path: ".." diff --git a/examples/hellostyle.nim b/examples/hellostyle.nim deleted file mode 100644 index 716c2f0..0000000 --- a/examples/hellostyle.nim +++ /dev/null @@ -1,17 +0,0 @@ -include karax / prelude -import karax / vstyles - -proc createDom(): VNode = - result = buildHtml(tdiv): - tdiv(style = style(StyleAttr.color, "red".cstring)): - text "red" - tdiv(style = style(StyleAttr.color, "blue")): - text "blue" - # explicit `kstring` required for varargs overload - tdiv(style = style((fontStyle, "italic".kstring), (color, "orange".kstring))): - text "italic orange" - # can use a string directly - tdiv(style = "font-style: oblique; color: pink".toCss): - text "oblique pink" - -setRenderer createDom diff --git a/examples/hellouniverse.nim b/examples/hellouniverse.nim deleted file mode 100644 index 8343d07..0000000 --- a/examples/hellouniverse.nim +++ /dev/null @@ -1,12 +0,0 @@ -include karax / prelude -import random - -proc createDom(): VNode = - result = buildHtml(tdiv): - if rand(100) <= 50: - text "Hello World!" - else: - text "Hello Universe" - -randomize() -setRenderer createDom diff --git a/examples/helloworld.nim b/examples/helloworld.nim deleted file mode 100644 index 76c43db..0000000 --- a/examples/helloworld.nim +++ /dev/null @@ -1,7 +0,0 @@ -include karax / prelude - -proc createDom(): VNode = - result = buildHtml(tdiv): - text "Hello World!" - -setRenderer createDom diff --git a/examples/login.nim b/examples/login.nim deleted file mode 100644 index 0350e23..0000000 --- a/examples/login.nim +++ /dev/null @@ -1,46 +0,0 @@ -include karax / prelude -from sugar import `=>` -import karax / errors - -proc loginField(desc, field, class: kstring; - validator: proc (field: kstring): proc ()): VNode = - result = buildHtml(tdiv): - label(`for` = field): - text desc - input(class = class, id = field, onchange = validator(field)) - -# some consts in order to prevent typos: -const - username = kstring"username" - password = kstring"password" - -proc validateNotEmpty(field: kstring): proc () = - result = proc () = - let x = getVNodeById(field) - if x.text == "": - errors.setError(field, field & " must not be empty") - else: - errors.setError(field, "") - -var loggedIn: bool - -proc loginDialog(): VNode = - result = buildHtml(tdiv): - if not loggedIn: - loginField("Name: ", username, "input", validateNotEmpty) - loginField("Password: ", password, "password", validateNotEmpty) - button(onclick = () => (loggedIn = true), disabled = errors.disableOnError()): - text "Login" - p: - text errors.getError(username) - p: - text errors.getError(password) - else: - p: - text "You are now logged in." - -setError username, username & " must not be empty" -setError password, password & " must not be empty" - -when not declared(toychat): - setRenderer loginDialog diff --git a/examples/mediaplayer/mediaplayer.nim b/examples/mediaplayer/mediaplayer.nim index c84b68b..18179c1 100644 --- a/examples/mediaplayer/mediaplayer.nim +++ b/examples/mediaplayer/mediaplayer.nim @@ -1,5 +1,5 @@ -import karax / [karax, karaxdsl, vdom, kdom, compact] +import karax, karaxdsl, vdom, dom, components const Play = 0 @@ -12,10 +12,10 @@ proc play(n: Node) {.importcpp.} proc pause(n: Node) {.importcpp.} proc `width=`(n: Node, w: int) {.importcpp: "#.width = #".} -proc mplayer*(id, resource: cstring): VNode {.compact.} = +proc mplayer*(id, resource: cstring): VNode {.component.} = proc handler(ev: Event; n: VNode) = let myVideo = document.getElementById(id) - case n.index + case n.key of Play: if myVideo.paused: myVideo.play() @@ -27,13 +27,13 @@ proc mplayer*(id, resource: cstring): VNode {.compact.} = else: discard result = buildHtml(tdiv): - button(onclick=handler, index=Play): + button(onclick=handler, key=Play): text "Play/Pause" - button(onclick=handler, index=Big): + button(onclick=handler, key=Big): text "Big" - button(onclick=handler, index=Small): + button(onclick=handler, key=Small): text "Small" - button(onclick=handler, index=Normal): + button(onclick=handler, key=Normal): text "Normal" br() br() diff --git a/examples/mediaplayer/playerapp.html b/examples/mediaplayer/playerapp.html index a45a2e8..9e076e6 100644 --- a/examples/mediaplayer/playerapp.html +++ b/examples/mediaplayer/playerapp.html @@ -1,15 +1,15 @@ - - Player app - + + Player app + - + -
+
- + - + diff --git a/examples/mediaplayer/playerapp.nim b/examples/mediaplayer/playerapp.nim index acb2e68..e611eec 100644 --- a/examples/mediaplayer/playerapp.nim +++ b/examples/mediaplayer/playerapp.nim @@ -1,6 +1,6 @@ ## Example app that shows how to write and embed a custom component. -include karax/prelude +include karaxprelude import mediaplayer const url = "https://www.w3schools.com/html/mov_bbb.mp4" diff --git a/examples/mediaplayer/playerapp.nims b/examples/mediaplayer/playerapp.nims index cf2eb9e..9028ff1 100644 --- a/examples/mediaplayer/playerapp.nims +++ b/examples/mediaplayer/playerapp.nims @@ -1 +1 @@ ---path: "../.." +--path: "../../src" diff --git a/examples/scrollapp/scrollapp.html b/examples/scrollapp/scrollapp.html index 44d657e..1ff8b1b 100644 --- a/examples/scrollapp/scrollapp.html +++ b/examples/scrollapp/scrollapp.html @@ -1,15 +1,15 @@ - - Todo app - + + Todo app + - + -
+
- + - + diff --git a/examples/scrollapp/scrollapp.nim b/examples/scrollapp/scrollapp.nim index 4490447..e5ef9c1 100644 --- a/examples/scrollapp/scrollapp.nim +++ b/examples/scrollapp/scrollapp.nim @@ -1,7 +1,7 @@ ## Example that shows how to accomplish an "infinitely scrolling" app. -include karax/prelude -import karax / [jstrutils, kdom, vstyles] +include karaxprelude +import jstrutils, dom var entries: seq[cstring] = @[] for i in 1..500: @@ -16,8 +16,7 @@ proc scrollEvent(ev: Event; n: VNode) = proc createDom(): VNode = result = buildHtml(): - tdiv(onscroll=scrollEvent, style=style( - (StyleAttr.height, cstring"400px"), (StyleAttr.overflow, cstring"scroll"))): + tdiv(onscroll=scrollEvent, style="height: 400px; overflow: scroll"): for x in entries: tdiv: text x diff --git a/examples/scrollapp/scrollapp.nims b/examples/scrollapp/scrollapp.nims index cf2eb9e..9028ff1 100644 --- a/examples/scrollapp/scrollapp.nims +++ b/examples/scrollapp/scrollapp.nims @@ -1 +1 @@ ---path: "../.." +--path: "../../src" diff --git a/examples/todoapp/todoapp.html b/examples/todoapp/todoapp.html index ab3daa7..488a3bf 100644 --- a/examples/todoapp/todoapp.html +++ b/examples/todoapp/todoapp.html @@ -1,16 +1,16 @@ - - Todo app - - + + Todo app + + - + -
+
- + - + diff --git a/examples/todoapp/todoapp.nim b/examples/todoapp/todoapp.nim index e3720fd..802bfc9 100644 --- a/examples/todoapp/todoapp.nim +++ b/examples/todoapp/todoapp.nim @@ -1,5 +1,5 @@ -import karax / [vdom, karax, karaxdsl, jstrutils, compact, localstorage] +import vdom, karax, karaxdsl, jstrutils, components, localstorage type Filter = enum @@ -9,7 +9,7 @@ var selectedEntry = -1 filter: Filter entriesLen: int - doneswitch = true + const contentSuffix = cstring"content" completedSuffix = cstring"completed" @@ -41,30 +41,29 @@ proc updateEntry(pos: int, content: cstring, completed: bool) = markAsCompleted(pos, completed) proc onTodoEnter(ev: Event; n: VNode) = - if n.value.strip() != "": - addEntry(n.value, false) - n.value = "" + addEntry(n.value, false) + n.value = "" proc removeHandler(ev: Event; n: VNode) = - updateEntry(n.index, cstring(nil), false) + updateEntry(n.key, cstring(nil), false) proc editHandler(ev: Event; n: VNode) = - selectedEntry = n.index + selectedEntry = n.key proc focusLost(ev: Event; n: VNode) = selectedEntry = -1 proc editEntry(ev: Event; n: VNode) = - setEntryContent(n.index, n.value) + setEntryContent(n.key, n.value) selectedEntry = -1 proc toggleEntry(ev: Event; n: VNode) = - let id = n.index + let id = n.key markAsCompleted(id, not isCompleted(id)) proc onAllDone(ev: Event; n: VNode) = - for i in 0.. - + diff --git a/experiments/ajaxtest.nim b/experiments/ajaxtest.nim index 720b6b2..7af60cd 100644 --- a/experiments/ajaxtest.nim +++ b/experiments/ajaxtest.nim @@ -1,4 +1,4 @@ -import kdom, kajax +import dom, kajax proc cb(httpStatus: int, response: cstring) = echo "Worked!" diff --git a/experiments/config.nims b/experiments/config.nims deleted file mode 100644 index 86673aa..0000000 --- a/experiments/config.nims +++ /dev/null @@ -1,2 +0,0 @@ ---path: "../karax" ---path: ".." diff --git a/experiments/echartstest.html b/experiments/echartstest.html deleted file mode 100644 index 8c9b225..0000000 --- a/experiments/echartstest.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Karax ECharts Test - - - - -
- - - - diff --git a/experiments/echartstest.nim b/experiments/echartstest.nim deleted file mode 100644 index 950c6ce..0000000 --- a/experiments/echartstest.nim +++ /dev/null @@ -1,58 +0,0 @@ -import karax / [kbase, vdom, kdom, vstyles, karax, karaxdsl, jdict, jstrutils, jjson] - -type - Views = enum - Customers, Products - -var - currentView = Customers - -type - EChart* = ref object - -proc echartsInit(n: Element): EChart {.importc: "echarts.init".} -proc setOption(x: EChart; option: JsonNode) {.importcpp.} - -proc postRender(data: RouterData) = - if currentView == Products: - let myChart = echartsInit(kdom.getElementById("echartSection")) - # specify chart configuration item and data - let option = %*{ - "title": { - "text": "ECharts entry example" - }, - "tooltip": {}, - "legend": { - "data": ["Sales"] - }, - "xAxis": { - "data": ["shirt","cardign","chiffon shirt","pants","heels","socks"] - }, - "yAxis": {}, - "series": [{ - "name": "Sales", - "type": "bar", - "data": [5, 20, 36, 10, 10, 20] - }] - } - myChart.setOption(option) - -proc createDom(data: RouterData): VNode = - let hash = data.hashPart - if hash == cstring"#/Products": currentView = Products - else: currentView = Customers - - result = buildHtml(tdiv): - ul(class = "tabs"): - for v in low(Views)..high(Views): - li: - a(href = "#/" & $v): - text cstring($v) - - if currentView == Products: - tdiv(id = "echartSection", style = style((width, kstring"600px"), (height, kstring"400px"))) - tdiv: - text "other section" - -setRenderer createDom, "ROOT", postRender -setForeignNodeId "echartSection" diff --git a/experiments/example.html b/experiments/example.html new file mode 100644 index 0000000..2303d95 --- /dev/null +++ b/experiments/example.html @@ -0,0 +1,15 @@ + + + + + Todo app + + + + +
+ + + + + diff --git a/experiments/example.nim b/experiments/example.nim new file mode 100644 index 0000000..229cce6 --- /dev/null +++ b/experiments/example.nim @@ -0,0 +1,47 @@ + +import vdom, components, karax, karaxdsl, jdict, jstrutils, dom + +var + images: seq[cstring] = @[cstring"a", "b", "c", "d"] + +proc carousel*(key: VKey): VNode {.component.} = + state: + var counter: int = 0 + var cntdown: int = 5 + var timer: Timeout = nil + + proc docount() = + cntdown = cntdown - 1 + if cntdown == 0: + counter = (counter + 1) mod images.len + cntdown = 5 + else: + timer = setTimeout(docount, 30) + redraw() + + proc next(ev: Event; n: VNode) = + if timer != nil: + clearTimeout(timer) + timer = setTimeout(docount, 30) + + result = buildHtml(tdiv(key=key)): + text images[counter] + button(onclick = next): + text "Next" + if cntdown != 5: + text &cntdown + +proc createDom(): VNode = + result = buildHtml(table): + tr: + td: + carousel(0) + td: + carousel(1) + tr: + td: + carousel(2) + td: + carousel(3) + +setRenderer createDom diff --git a/experiments/example.nims b/experiments/example.nims new file mode 100644 index 0000000..6b5771c --- /dev/null +++ b/experiments/example.nims @@ -0,0 +1 @@ +--path: "../src" diff --git a/experiments/menus.nim b/experiments/menus.nim deleted file mode 100644 index 6ea0529..0000000 --- a/experiments/menus.nim +++ /dev/null @@ -1,65 +0,0 @@ -## Example program that shows how to create menus with Karax. - -include prelude -import jstrutils, kdom - -proc contentA(): VNode = - result = buildHtml(tdiv): - text "content A" - -proc contentB(): VNode = - result = buildHtml(tdiv): - text "content B" - -proc contentC(): VNode = - result = buildHtml(tdiv): - text "content C" - - - -type - MenuItemHandler = proc(): VNode - -var content: MenuItemHandler = contentA - -proc menuAction(x: MenuItemHandler): proc() = - result = proc() = content = x - -proc buildMenu(): VNode = - result = buildHtml(tdiv): - nav(class="navbar is-primary"): - tdiv(class="navbar-brand"): - a(class="navbar-item", onclick = menuAction(contentA)): - strong: - text "My awesome menu" - - tdiv(id="navMenuTransparentExample", class="navbar-menu"): - tdiv(class = "navbar-start"): - tdiv(class="navbar-item has-dropdown is-hoverable"): - a(class="navbar-link", onclick = menuAction(contentB)): - text "Masters" - tdiv(class="navbar-dropdown is-boxed"): - a(class="navbar-item", onclick = menuAction(contentC)): - text "Inventory" - a(class="navbar-item", onclick = menuAction(contentC)): - text "Product" - hr(class="navbar-divider"): - a(class="navbar-item", onclick = menuAction(contentC)): - text "Product" - - tdiv(class="navbar-item has-dropdown is-hoverable"): - a(class="navbar-link", onclick = menuAction(contentC)): - text "Transactions" - tdiv(class = "navbar-dropdown is-boxed", id="blogDropdown"): - a(class="navbar-item", onclick = menuAction(contentC)): - text "Purchase Bill" - a(class="navbar-item", onclick = menuAction(contentC)): - text "Purchase Return" - a(class="navbar-item", onclick = menuAction(contentC)): - text "Sale Bill" - hr(class="navbar-divider"): - a(class="navbar-item", onclick = menuAction(contentC)): - text "Stock Adjustment" - content() - -setRenderer buildMenu diff --git a/experiments/nativenodes.nim b/experiments/nativenodes.nim deleted file mode 100644 index 9d255ee..0000000 --- a/experiments/nativenodes.nim +++ /dev/null @@ -1,18 +0,0 @@ - - -include karax / prelude -import karax / kdom - -proc myInput: VNode = - result = buildHtml: - input() - -var inp = vnodeToDom(myInput()) - -proc myAwesomeComponent(x: Node): VNode = - result = dthunk(x) - -proc main: VNode = - result = myAwesomeComponent(inp) - -setRenderer main diff --git a/experiments/nextgen.nim b/experiments/nextgen.nim deleted file mode 100644 index 56330d0..0000000 --- a/experiments/nextgen.nim +++ /dev/null @@ -1,120 +0,0 @@ - -import vdom, kdom, vstyles, karax, karaxdsl, jdict, jstrutils, reactive - -proc textInput*(text: RString; focus: RBool): VNode {.track.} = - proc onFlip(ev: Event; target: VNode) = - focus <- not focus.value - - proc onKeyupEnter(ev: Event; target: VNode) = - text <- target.value - - proc onkeyup(ev: Event; n: VNode) = - # keep displayValue up to date, but do not tell the client yet! - text.value = n.value - - result = buildHtml(input(`type`="text", - value=text.value, onblur=onFlip, onfocus=onFlip, - onkeyupenter=onkeyupenter, onkeyup=onkeyup, setFocus=focus.value)) - -var - errmsg = rstr("") - -makeReactive: - type - User = ref object - firstname, lastname: cstring - selected: bool - -var gu = newRSeq(@[ (User(rawFirstname: "Some", rawLastname: "Body")), - (User(rawFirstname: "Some", rawLastname: "One")), - (User(rawFirstname: "Some", rawLastname: "Two"))]) -var prevSelected: User = nil #newReactive[User](nil) - -proc unselect() = - if prevSelected != nil: - prevSelected.selected = false - prevSelected = nil - -proc select(u: User) = - unselect() - u.selected = true - prevSelected = u - -proc toUI*(isFirstname: bool): RString = - result = RString() - result.subscribe proc (v: cstring) = - if v.len > 0: - let p = prevSelected #selected.value - if p != nil: - if isFirstName: - p.firstname = v - else: - p.lastname = v - unselect() - errmsg <- "" - else: - errmsg <- "name must not be empty" - -var inpFirstname = toUI(true) -var inpLastname = toUI(false) - -proc adaptFocus(def = false): RBool = - result = RBool() - result.value = def - when false: - result.subscribe proc (hasFocus: bool) = - if not hasFocus: - unselect() - -var focusA = adaptFocus() -var focusB = adaptFocus() - -proc styler(): VStyle = - result = style( - (StyleAttr.position, cstring"relative"), - (StyleAttr.paddingLeft, cstring"10px"), - (StyleAttr.paddingRight, cstring"5px"), - (StyleAttr.height, cstring"30px"), - (StyleAttr.lineHeight, cstring"30px"), - (StyleAttr.border, cstring"solid 8px " & (if focusA.value: cstring"red" else: cstring"black")), - (StyleAttr.fontSize, cstring"12px"), - (StyleAttr.fontWeight, cstring"600") - ) - -var clicks = 0 - -proc renderUser(u: User): VNode {.track.} = - result = buildHtml(tdiv): - if u.selected: - inpFirstname <- u.firstname - tdiv: - textInput inpFirstname, focusA - inpLastname <- u.lastname - tdiv: - textInput inpLastname, focusB - else: - button: - text "..." - proc onclick(ev: Event; n: VNode) = - select(u) - text u.firstname & " " & u.lastname - button: - text "(x)" - proc onclick(ev: Event; n: VNode) = - gu.deleteElem(u) - -proc main(gu: RSeq[User]): VNode = - result = buildHtml(tdiv): - tdiv: - button: - text "Add User" - proc onclick(ev: Event; n: VNode) = - inc clicks - gu.add User(rawFirstname: "Added", rawLastname: &clicks) - tdiv: - text errmsg - vmapIt(gu, tdiv, renderUser(it)) - -proc init(): VNode = main(gu) - -setInitializer(init) diff --git a/experiments/refs/demo.html b/experiments/refs/demo.html deleted file mode 100644 index 941333a..0000000 --- a/experiments/refs/demo.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - Refs - - - -
- - - diff --git a/experiments/refs/demo.nim b/experiments/refs/demo.nim deleted file mode 100644 index a0db59f..0000000 --- a/experiments/refs/demo.nim +++ /dev/null @@ -1,58 +0,0 @@ -include karaxprelude -import future, sequtils - -type - CustomRef = ref object of VComponent - -method onAttach(r: CustomRef) = - kout(cstring"custom ref attached") - -method onDetach(r: CustomRef) = - kout(cstring"custom ref detached") - -var - modelData = @[5, 2, 4] - - refA = VComponent() - refB = VComponent() - refC = CustomRef() - refSeq = newSeq[VComponent]() - -proc onClick(ev: Event, n: VNode) = - modelData.add(0) - -proc showRefs() = - kout(refA) - kout(refB) - kout(refC) - for i in 0 ..< refSeq.len: - kout(refSeq[i].vnode) - #kout(refSeq.map(nref => nref.vnode)) - -proc secureRefSlot(i: int): VComponent = - while refSeq.len <= i: - refSeq.add(VComponent()) - result = refSeq[i] - -proc view(): VNode = - result = buildHtml(): - tdiv: - button(onclick=onClick): - text "click me" - # storing refs to single elements is straightforward now - if modelData.len mod 2 == 0: - tdiv(nref=refA): - text "A" - tdiv(nref=refB): - text "B" - tdiv(nref=refC): - text "C" - # It's a bit more tricky when containers are involved: - for i, x in modelData.pairs: - tdiv(nref=secureRefSlot(i)): - text "List item: " & $x - -proc renderer(): VNode = - view() - -setRenderer(renderer, "ROOT", showRefs) diff --git a/experiments/refs/demo.nims b/experiments/refs/demo.nims deleted file mode 100644 index 9028ff1..0000000 --- a/experiments/refs/demo.nims +++ /dev/null @@ -1 +0,0 @@ ---path: "../../src" diff --git a/experiments/scrollapp.html b/experiments/scrollapp.html index 8b909f1..ad3ce2f 100644 --- a/experiments/scrollapp.html +++ b/experiments/scrollapp.html @@ -10,7 +10,7 @@
- + diff --git a/experiments/scrollapp.nim b/experiments/scrollapp.nim index 86a802f..f9c8ccb 100644 --- a/experiments/scrollapp.nim +++ b/experiments/scrollapp.nim @@ -1,5 +1,5 @@ -import vdom, karax, karaxdsl, jdict, jstrutils, compact +import vdom, karax, karaxdsl, jdict, jstrutils, components type Filter = enum diff --git a/experiments/scrollapp.nims b/experiments/scrollapp.nims new file mode 100644 index 0000000..532b206 --- /dev/null +++ b/experiments/scrollapp.nims @@ -0,0 +1 @@ +--path: "../src" diff --git a/experiments/scrollapp_simple.nim b/experiments/scrollapp_simple.nim deleted file mode 100644 index cdd19cd..0000000 --- a/experiments/scrollapp_simple.nim +++ /dev/null @@ -1,25 +0,0 @@ -## Example that shows how to accomplish an "infinitely scrolling" app. - -include karax / prelude -import karax / [kdom, vstyles] - -var entries: seq[cstring] = @[] -for i in 1..500: - entries.add(cstring("Entry ") & &i) - -proc scrollEvent(ev: Event; n: VNode) = - let d = n.dom - if d != nil and inViewport(d.lastChild): - # "load" more data: - for i in 1..50: - entries.add(cstring("Loaded Entry ") & &i) - -proc createDom(): VNode = - result = buildHtml(): - tdiv(onscroll=scrollEvent, style=style( - (StyleAttr.height, cstring"400px"), (StyleAttr.overflow, cstring"scroll"))): - for x in entries: - tdiv: - text x - -setRenderer createDom diff --git a/experiments/trello/knete.nim b/experiments/trello/knete.nim deleted file mode 100644 index 3a09ee3..0000000 --- a/experiments/trello/knete.nim +++ /dev/null @@ -1,752 +0,0 @@ -## Raw DOM manipulation. No DOM diff'ing, no cry. - -import macros, tables -from strutils import startsWith, toLowerAscii, toUpperAscii - -when defined(js): - type kstring* = cstring -else: - type kstring* = string - -type - Tag* {.pure.} = enum - text = "#text", - - html, head, title, base, link, meta, style, - script, noscript, - body, section, nav, article, aside, - h1, h2, h3, h4, h5, h6, - header, footer, address, main - - p, hr, pre, blockquote, ol, ul, li, - dl, dt, dd, - figure, figcaption, - - tdiv = "div", - - a, em, strong, small, - strikethrough = "s", cite, quote, - dfn, abbr, data, time, code, `var` = "var", samp, - kdb, sub, sup, italic = "i", bold = "b", underlined = "u", - mark, ruby, rt, rp, bdi, dbo, span, br, wbr, - ins, del, img, iframe, embed, `object` = "object", - param, video, audio, source, track, canvas, map, - area, svg, math, - - table, caption, colgroup, col, tbody, thead, - tfoot, tr, td, th, - - form, fieldset, legend, label, input, button, - select, datalist, optgroup, option, textarea, - keygen, output, progress, meter, - details, summary, command, menu - -type - EventKind* {.pure.} = enum ## The events supported by the virtual DOM. - onclick, ## An element is clicked. - oncontextmenu, ## An element is right-clicked. - ondblclick, ## An element is double clicked. - onkeyup, ## A key was released. - onkeydown, ## A key is pressed. - onkeypressed, # A key was pressed. - onfocus, ## An element got the focus. - onblur, ## An element lost the focus. - onchange, ## The selected value of an element was changed. - onscroll, ## The user scrolled within an element. - - onmousedown, ## A pointing device button (usually a mouse) is pressed - ## on an element. - onmouseenter, ## A pointing device is moved onto the element that - ## has the listener attached. - onmouseleave, ## A pointing device is moved off the element that - ## has the listener attached. - onmousemove, ## A pointing device is moved over an element. - onmouseout, ## A pointing device is moved off the element that - ## has the listener attached or off one of its children. - onmouseover, ## A pointing device is moved onto the element that has - ## the listener attached or onto one of its children. - onmouseup, ## A pointing device button is released over an element. - - ondrag, ## An element or text selection is being dragged (every 350ms). - ondragend, ## A drag operation is being ended (by releasing a mouse button - ## or hitting the escape key). - ondragenter, ## A dragged element or text selection enters a valid drop target. - ondragleave, ## A dragged element or text selection leaves a valid drop target. - ondragover, ## An element or text selection is being dragged over a valid - ## drop target (every 350ms). - ondragstart, ## The user starts dragging an element or text selection. - ondrop, ## An element is dropped on a valid drop target. - - onsubmit, ## A form is submitted - oninput, ## An input value changes - - onkeyupenter, ## vdom extension: an input field received the ENTER key press - onkeyuplater ## vdom extension: a key was pressed and some time - ## passed (useful for on-the-fly text completions) - - -macro buildLookupTables(): untyped = - var a = newTree(nnkBracket) - for i in low(Tag)..high(Tag): - let x = $i - let y = if x[0] == '#': x else: toUpperAscii(x) - a.add(newCall("kstring", newLit(y))) - var e = newTree(nnkBracket) - for i in low(EventKind)..high(EventKind): - e.add(newCall("kstring", newLit(substr($i, 2)))) - - template tmpl(a, e) {.dirty.} = - const - toTagName*: array[Tag, kstring] = a - toEventName*: array[EventKind, kstring] = e - - result = getAst tmpl(a, e) - -buildLookupTables() - -# ---------------- CSS ---------------------------------------------- - -type - StyleAttr* {.pure.} = enum - ## The style attributes supported by the virtual DOM. - ## Reference: https://www.w3schools.com/jsref/dom_obj_style.asp - alignContent - alignItems - alignSelf - animation - animationDelay - animationDirection - animationDuration - animationFillMode - animationIterationCount - animationName - animationTimingFunction - animationPlayState - background - backgroundAttachment - backgroundColor - backgroundImage - backgroundPosition - backgroundRepeat - backgroundClip - backgroundOrigin - backgroundSize - backfaceVisibility - border - borderBottom - borderBottomColor - borderBottomLeftRadius - borderBottomRightRadius - borderBottomStyle - borderBottomWidth - borderCollapse - borderColor - borderImage - borderImageOutset - borderImageRepeat - borderImageSlice - borderImageSource - borderImageWidth - borderLeft - borderLeftColor - borderLeftStyle - borderLeftWidth - borderRadius - borderRight - borderRightColor - borderRightStyle - borderRightWidth - borderSpacing - borderStyle - borderTop - borderTopColor - borderTopLeftRadius - borderTopRightRadius - borderTopStyle - borderTopWidth - borderWidth - bottom - boxDecorationBreak - boxShadow - boxSizing - captionSide - clear - clip - color - columnCount - columnFill - columnGap - columnRule - columnRuleColor - columnRuleStyle - columnRuleWidth - columns - columnSpan - columnWidth - content - counterIncrement - counterReset - cursor - direction - display - emptyCells - filter - flex - flexBasis - flexDirection - flexFlow - flexGrow - flexShrink - flexWrap - cssFloat - font - fontFamily - fontSize - fontSizeAdjust - fontStretch - fontStyle - fontVariant - fontWeight - hangingPunctuation - height - hyphens - icon - imageOrientation - justifyContent - left - letterSpacing - lineHeight - listStyle - listStyleImage - listStylePosition - listStyleType - margin - marginBottom - marginLeft - marginRight - marginTop - maxHeight - maxWidth - minHeight - minWidth - navDown - navIndex - navLeft - navRight - navUp - opacity - order - orphans - outline - outlineColor - outlineOffset - outlineStyle - outlineWidth - overflow - overflowX - overflowY - padding - paddingBottom - paddingLeft - paddingRight - paddingTop - pageBreakAfter - pageBreakBefore - pageBreakInside - perspective - perspectiveOrigin - pointerEvents - position - quotes - resize - right - scrollbar3dLightColor # note: missing in w3schools reference - scrollbarArrowColor # note: missing in w3schools reference - scrollbarBaseColor # note: missing in w3schools reference - scrollbarDarkshadowColor # note: missing in w3schools reference - scrollbarFaceColor # note: missing in w3schools reference - scrollbarHighlightColor # note: missing in w3schools reference - scrollbarShadowColor # note: missing in w3schools reference - scrollbarTrackColor # note: missing in w3schools reference - tableLayout - tabSize - textAlign - textAlignLast - textDecoration - textDecorationColor - textDecorationLine - textDecorationStyle - textIndent - textJustify - textOverflow - textShadow - textTransform - top - transform - transformOrigin - transformStyle - transition - transitionDelay - transitionDuration - transitionProperty - transitionTimingFunction - unicodeBidi - userSelect - verticalAlign - visibility - whiteSpace - width - wordBreak - wordSpacing - wordWrap - widows - zIndex - -macro buildStyleLookupTable(): untyped = - var e = newTree(nnkBracket) - for i in low(StyleAttr)..high(StyleAttr): - e.add(newCall("kstring", newLit($i))) - template tmpl(e) {.dirty.} = - const - toStyleAttrName: array[StyleAttr, kstring] = e - result = getAst tmpl(e) - -buildStyleLookupTable() - -type - StyleObj {.importc.} = object - background*: cstring - backgroundAttachment*: cstring - backgroundColor*: cstring - backgroundImage*: cstring - backgroundPosition*: cstring - backgroundRepeat*: cstring - border*: cstring - borderBottom*: cstring - borderBottomColor*: cstring - borderBottomStyle*: cstring - borderBottomWidth*: cstring - borderColor*: cstring - borderLeft*: cstring - borderLeftColor*: cstring - borderLeftStyle*: cstring - borderLeftWidth*: cstring - borderRight*: cstring - borderRightColor*: cstring - borderRightStyle*: cstring - borderRightWidth*: cstring - borderStyle*: cstring - borderTop*: cstring - borderTopColor*: cstring - borderTopStyle*: cstring - borderTopWidth*: cstring - borderWidth*: cstring - bottom*: cstring - captionSide*: cstring - clear*: cstring - clip*: cstring - color*: cstring - cursor*: cstring - direction*: cstring - display*: cstring - emptyCells*: cstring - cssFloat*: cstring - font*: cstring - fontFamily*: cstring - fontSize*: cstring - fontStretch*: cstring - fontStyle*: cstring - fontVariant*: cstring - fontWeight*: cstring - height*: cstring - left*: cstring - letterSpacing*: cstring - lineHeight*: cstring - listStyle*: cstring - listStyleImage*: cstring - listStylePosition*: cstring - listStyleType*: cstring - margin*: cstring - marginBottom*: cstring - marginLeft*: cstring - marginRight*: cstring - marginTop*: cstring - maxHeight*: cstring - maxWidth*: cstring - minHeight*: cstring - minWidth*: cstring - overflow*: cstring - padding*: cstring - paddingBottom*: cstring - paddingLeft*: cstring - paddingRight*: cstring - paddingTop*: cstring - pageBreakAfter*: cstring - pageBreakBefore*: cstring - pointerEvents*: cstring - position*: cstring - right*: cstring - scrollbar3dLightColor*: cstring - scrollbarArrowColor*: cstring - scrollbarBaseColor*: cstring - scrollbarDarkshadowColor*: cstring - scrollbarFaceColor*: cstring - scrollbarHighlightColor*: cstring - scrollbarShadowColor*: cstring - scrollbarTrackColor*: cstring - tableLayout*: cstring - textAlign*: cstring - textDecoration*: cstring - textIndent*: cstring - textTransform*: cstring - transform*: cstring - top*: cstring - verticalAlign*: cstring - visibility*: cstring - width*: cstring - wordSpacing*: cstring - zIndex*: int - Style* = ref StyleObj - - ElementObj {.importc.} = object - id*, class*, value*: cstring - disabled*: bool - style*: Style - Element* = ref ElementObj - - DocumentObj {.importc.} = object - Document = ref DocumentObj - -proc setStyle(s: Style; key, val: cstring) {.importcpp: "#[#] = #", noSideEffect.} - -proc applyStyles*(e: Element; pairs: openArray[(StyleAttr, kstring)]) = - for x in pairs: - e.style.setStyle(toStyleAttrName[x[0]], x[1]) - -# ------- Tree manipulation --------------------------- - -var document {.importc.}: Document - -proc parent*(x: Element): Element {.importcpp: "#.parentNode".} - -proc up*(x: Element; className: cstring): Element = - result = x - while result != nil and result.class != className: - result = result.parent - -proc len*(x: Element): int {.importcpp: "#.childNodes.length".} -proc `[]`*(x: Element; idx: int): Element {.importcpp: "#.childNodes[#]".} -proc getElementById*(id: cstring): Element {.importc: "document.getElementById", nodecl.} -proc add*(n, child: Element) {.importcpp: "appendChild".} - -proc removeChild(n, child: Element) {.importcpp.} -proc replaceChild(n, newNode, oldNode: Element) {.importcpp.} - -proc replace*(self, by: Element) = replaceChild(self.parent, by, self) -proc delete*(self: Element) = removeChild(self.parent, self) - -proc insertBefore(n, newNode, before: Element) {.importcpp.} -proc insert*(before, newNode: Element) = insertBefore(before.parent, newNode, before) - -proc createTextNode(d: Document, text: cstring): Element {.importcpp.} -proc text*(s: kstring): Element = createTextNode(document, s) - -iterator items*(n: Element): Element = - for i in 0.. 0: - result[L-1] = tcall2(result[L-1], tmpContext) - of nnkStmtList, nnkStmtListExpr, nnkWhenStmt, nnkIfStmt, nnkTryStmt, - nnkFinally: - # recurse for every child: - result = copyNimNode(n) - for x in n: - result.add tcall2(x, tmpContext) - of nnkCaseStmt: - # recurse for children, but don't add call for case ident - result = copyNimNode(n) - result.add n[0] - for i in 1 ..< n.len: - result.add tcall2(n[i], tmpContext) - of nnkProcDef: - let name = getName n[0] - if name.startsWith"on": - # turn it into an anon proc: - let anon = copyNimTree(n) - anon[0] = newEmptyNode() - if tmpContext == nil: - error "no Element to attach the event handler to" - else: - result = newCall(evHandler(), tmpContext, - newDotExpr(bindSym"EventKind", n[0]), anon, ident("kxi")) - else: - result = n - of nnkVarSection, nnkLetSection, nnkConstSection: - result = n - of nnkCallKinds - {nnkInfix}: - let op = getName(n[0]) - if isComponent(op) == ComponentKind.Tag: - let tmp = genSym(nskLet, "tmp") - let call = newCall(bindSym"tree", newDotExpr(bindSym"Tag", n[0])) - result = newTree( - if tmpContext == nil: nnkStmtListExpr else: nnkStmtList, - newLetStmt(tmp, call)) - for i in 1 ..< n.len: - # named parameters are transformed into attributes or events: - let x = n[i] - if x.kind == nnkExprEqExpr: - let key = getName x[0] - if key.startsWith("on"): - result.add newCall(evHandler(), - tmp, newDotExpr(bindSym"EventKind", x[0]), x[1]) - elif key in SpecialAttrs: - result.add newDotAsgn(tmp, key, x[1]) - elif eqIdent(key, "style"): - result.add newCall(bindSym"applyStyles", tmp, toKstring x[1]) - elif eqIdent(key, "setFocus"): - result.add newCall(bindSym"focus", tmp) - else: - result.add newCall(bindSym"setAttr", tmp, newLit(key), x[1]) - elif eqIdent(x, "setFocus"): - result.add newCall(bindSym"focus", tmp) - else: - result.add tcall2(x, tmp) - if tmpContext == nil: - result.add tmp - else: - result.add newCall(bindSym"add", tmpContext, tmp) - elif tmpContext != nil and op notin StmtContext: - var hasEventHandlers = false - for i in 1..= 0.18.0" -requires "ws" -requires "dotenv" -skipDirs = @["examples", "experiments", "tests"] +requires "nim >= 0.16.1" -bin = @["karax/tools/karun"] -installExt = @["nim"] +skipDirs = @["examples/todoapp"] \ No newline at end of file diff --git a/karax/autocomplete.nim b/karax/autocomplete.nim deleted file mode 100644 index 210ed4a..0000000 --- a/karax/autocomplete.nim +++ /dev/null @@ -1,160 +0,0 @@ - -import karax, karaxdsl, vdom, kdom, jstrutils - -type - AutocompleteState* = ref object - choices, candidates: seq[cstring] - selected, maxMatches: int - showCandidates, controlPressed: bool - -proc newAutocomplete*(choices: seq[cstring]; maxMatches = 5): AutocompleteState = - ## Creates a new state for the autocomplete widget. ``maxMatches`` is the maximum - ## number of elements to show. - AutocompleteState(choices: choices, candidates: @[], - selected: -1, maxMatches: maxMatches, showCandidates: false, - controlPressed: false) - -proc autocomplete*(s: AutocompleteState; onselection: proc(s: cstring)): VNode = - var inp: VNode - - proc commit(ev: Event) = - s.showCandidates = false - onselection(inp.dom.value) - when false: - if inp.dom != nil: - echo "setting to A ", inp.dom.value.isNil - result.text = inp.dom.value - else: - echo "setting to B ", inp.text.isNil - result.text = inp.text - for e in result.events: - if e[0] == EventKind.onchange: - e[1](ev, result) - - proc onkeyuplater(ev: Event; n: VNode) = - if not s.controlPressed: - let v = n.value - s.candidates.setLen 0 - for c in s.choices: - if v.len == 0 or c.containsIgnoreCase(v): s.candidates.add(c) - - proc onkeydown(ev: Event; n: VNode) = - const - LEFT = 37 - UP = 38 - RIGHT = 39 - DOWN = 40 - TAB = 9 - ESC = 27 - ENTER = 13 - # UP: Move focus to the previous item. If on first item, move focus to the input. - # If on the input, move focus to last item. - # DOWN: Move focus to the next item. If on last item, move focus to the input. - # If on the input, move focus to the first item. - # ESCAPE: Close the menu. - # ENTER: Select the currently focused item and close the menu. - # TAB: Select the currently focused item, close the menu, and - # move focus to the next focusable element - s.controlPressed = false - case ev.keyCode - of UP: - s.controlPressed = true - s.showCandidates = true - if s.selected > 0: - dec s.selected - n.setInputText s.candidates[s.selected] - of DOWN: - s.controlPressed = true - s.showCandidates = true - if s.selected < s.candidates.len - 1: - inc s.selected - n.setInputText s.candidates[s.selected] - of ESC: - s.showCandidates = false - s.controlPressed = true - of ENTER: - s.controlPressed = true -# inp.setInputText s.choices[i] - commit(ev) - else: - discard - - proc window(s: AutocompleteState): (int, int) = - var first, last: int - if s.selected >= 0: - first = s.selected - (s.maxMatches div 2) - last = s.selected + (s.maxMatches div 2) - if first < 0: first = 0 - # too few because we had to trim first? - if (last - first + 1) < s.maxMatches: last = first + s.maxMatches - 1 - else: - first = 0 - last = s.maxMatches - 1 - if last > high(s.candidates): last = high(s.candidates) - # still too few because we're at the end? - if (last - first + 1) < s.maxMatches: - first = last - s.maxMatches + 1 - if first < 0: first = 0 - - result = (first, last) - - inp = buildHtml: - input(onkeyuplater = onkeyuplater, - onkeydown = onkeydown, - # onblur = proc (ev: Event; n: VNode) = commit(ev), - onfocus = proc (ev: Event; n: VNode) = - onkeyuplater(ev, n) - s.showCandidates = true) - - proc select(i: int): proc(ev: Event; n: VNode) = - result = proc(ev: Event; n: VNode) = - s.selected = i - s.showCandidates = false - inp.setInputText s.choices[i] - commit(ev) - - result = buildHtml(table): - tr: - td: - inp - if s.showCandidates: - let (first, last) = window(s) - for i in first..last: - tr: - td(onclick = select(i), class = cstring"button " & - (if i == s.selected: cstring"is-primary" else: "")): - text s.candidates[i] - -when isMainModule: - const suggestions = @[cstring"ActionScript", - "AppleScript", - "Asp", - "BASIC", - "C", - "C++", - "Clojure", - "COBOL", - "Erlang", - "Fortran", - "Groovy", - "Haskell", - "Java", - "JavaScript", - "Lisp", - "Nim", - "Perl", - "PHP", - "Python", - "Ruby", - "Scala", - "Scheme"] - - var s = newAutocomplete(suggestions) - - proc main(): VNode = - result = buildHtml(tdiv): - autocomplete(s, proc (s: cstring) = echo "now ", s)#: - # proc onchange(ev: Event; n: VNode) = - # echo "now selected ", n.kind - - setRenderer(main) diff --git a/karax/compact.nim b/karax/compact.nim deleted file mode 100644 index 4e5dd6d..0000000 --- a/karax/compact.nim +++ /dev/null @@ -1,114 +0,0 @@ -## Components in Karax are built by the ``.component`` macro annotation. - -when defined(js): - import jdict, kdom - -import macros, vdom, tables, strutils, kbase - -when defined(js): - var - vcomponents* = newJDict[cstring, proc(args: seq[VNode]): VNode]() -else: - var - vcomponents* = newTable[kstring, proc(args: seq[VNode]): VNode]() - -type - ComponentKind* {.pure.} = enum - None, - Tag, - VNode - -var - allcomponents {.compileTime.} = initTable[string, ComponentKind]() - -proc isComponent*(x: string): ComponentKind {.compileTime.} = - allcomponents.getOrDefault(x) - -proc addTags() {.compileTime.} = - let x = (bindSym"VNodeKind").getTypeImpl - expectKind(x, nnkEnumTy) - for i in ord(VNodeKind.html)..ord(VNodeKind.high): - # +1 because of empty node at the start of the enum AST: - let tag = $x[i+1] - allcomponents[tag] = ComponentKind.Tag - -static: - addTags() - -proc unpack(symbolicType: NimNode; index: int): NimNode {.compileTime.} = - #let t = symbolicType.getTypeImpl - let t = repr(symbolicType) - case t - of "cstring": - result = quote do: - args[`index`].text - of "int", "VKey": - result = quote do: - args[`index`].intValue - of "bool": - result = quote do: - args[`index`].intValue != 0 - elif t.endsWith"Kind": - result = quote do: - `symbolicType`(args[`index`].intValue) - else: - # just pass it along, maybe there is some conversion for it: - result = quote do: - args[`index`] - -proc newname*(n: NimNode): NimNode = - if n.kind == nnkPostfix: - n[1] = newname(n[1]) - result = n - elif n.kind == nnkSym: - result = ident(n.strVal) - else: - result = n - -when defined(js): - macro compact*(prc: untyped): untyped = - ## A 'compact' tree generation proc is one that only depends on its - ## inputs and should be stored as a compact virtual DOM tree and - ## only expanded on demand (when its inputs changed). - var n = prc.copyNimNode - for i in 0..6: n.add prc[i].copyNimTree - expectKind(n, nnkProcDef) - if n[0].kind == nnkEmpty: - error("please pass a non anonymous proc", n[0]) - let name = n[0] - let params = params(n) - let rettype = repr params[0] - var isvirtual = ComponentKind.None - if rettype == "VNode": - isvirtual = ComponentKind.VNode - else: - error "component must return VNode", params[0] - let realName = if name.kind == nnkPostfix: name[1] else: name - let nn = $realName - n[0] = ident("inner" & nn) - var unpackCall = newCall(n[0]) - var counter = 0 - for i in 1 ..< params.len: - let param = params[i] - let L = param.len - let typ = param[L-2] - for j in 0 .. L-3: - unpackCall.add unpack(typ, counter) - inc counter - - template vwrapper(pname, unpackCall) {.dirty.} = - proc pname(args: seq[VNode]): VNode = - unpackCall - - template vregister(key, val) = - bind jdict.`[]=` - `[]=`(vcomponents, kstring(key), val) - - result = newTree(nnkStmtList, n) - - if isvirtual == ComponentKind.VNode: - result.add getAst(vwrapper(newname name, unpackCall)) - result.add getAst(vregister(newLit(nn), realName)) - allcomponents[nn] = isvirtual - when defined(debugKaraxDsl): - echo repr result diff --git a/karax/errors.nim b/karax/errors.nim deleted file mode 100644 index aedd103..0000000 --- a/karax/errors.nim +++ /dev/null @@ -1,32 +0,0 @@ -## Error handling logic for form input validation. - -import karax, jdict - -var - gerrorMsgs = newJDict[cstring, cstring]() - gerrorCounter = 0 - -proc hasErrors*(): bool = gerrorCounter != 0 - -proc hasError*(field: cstring): bool = gerrorMsgs.contains(field) and len(gerrorMsgs[field]) > 0 - -proc disableOnError*(): cstring = toDisabled(hasErrors()) - -proc getError*(field: cstring): cstring = - if not gerrorMsgs.contains(field): - result = "" - else: - result = gerrorMsgs[field] - -proc setError*(field, msg: cstring) = - let previous = getError(field) - if len(msg) == 0: - if len(previous) != 0: dec(gerrorCounter) - else: - if len(previous) == 0: inc(gerrorCounter) - gerrorMsgs[field] = msg - -proc clearErrors*() = - let m = gerrorMsgs - for k in m.keys: - setError(k, "") diff --git a/karax/i18n.nim b/karax/i18n.nim deleted file mode 100644 index 42274ff..0000000 --- a/karax/i18n.nim +++ /dev/null @@ -1,152 +0,0 @@ -## Karax -- Single page applications for Nim. - -## i18n support for Karax applications. We distinguish between: -## -## - translate: Lookup text translations -## - localize: Localize Date and Time objects to local formats -## -## Localization has not yet been implemented. - -import languages, jdict, jstrutils - -var currentLanguage = Language.enUS - -proc getLanguage(): cstring = - {.emit: "`result` = (navigator.languages && navigator.languages.length) ? navigator.languages[0] : navigator.language;".} - -proc detectLanguage*(): Language = - let x = getLanguage() - for i in low(Language)..high(Language): - if languageToCode[i] == x: return i - return Language.enUS - -proc setCurrentLanguage*(newLanguage = detectLanguage()) = - currentLanguage = newLanguage - -proc getCurrentLanguage*(): Language = currentLanguage - -type Translation* = JDict[cstring, cstring] - -var - translations: array[Language, Translation] - -proc registerTranslation*(lang: Language; t: Translation) = translations[lang] = t - -proc addTranslation*(lang: Language; key, val: cstring) = - if translations[lang].isNil: translations[lang] = newJDict[cstring, cstring]() - translations[lang][key] = val - -proc translate(x: cstring): cstring = - let y = translations[currentLanguage] - if y != nil and y.contains(x): - result = y[x] - else: - result = x - -type TranslatedString* = distinct cstring - -template i18n*(x: string): TranslatedString = TranslatedString(translate(cstring x)) - -proc raiseInvalidFormat(errmsg: string) = - raise newException(ValueError, errmsg) - -discard """ - $[1:item|items]1$ selected. -""" - -proc `{}`(x: cstring; i: int): char {.importcpp: "#.charCodeAt(#)".} -proc sadd(s: JSeq[char]; c: char) {.importcpp: "#.push(String.fromCharCode(#))".} - -proc parseChoice(f: cstring; i, choice: int, - r: JSeq[char]) = - var i = i - while i < f.len: - var n = 0 - let oldI = i - var toAdd = false - while i < f.len and f{i} >= '0' and f{i} <= '9': - n = n * 10 + ord(f{i}) - ord('0') - inc i - if oldI != i: - if f{i} == ':': - inc i - else: - raiseInvalidFormat"':' after number expected" - toAdd = choice == n - else: - # an else section does not start with a number: - toAdd = true - while i < f.len and f{i} != ']' and f{i} != '|': - if toAdd: r.sadd f{i} - inc i - if toAdd: break - inc i - -proc join(x: JSeq[char]): cstring {.importcpp: "#.join(\"\")".} -proc add(x: JSeq[char]; y: cstring) = - for i in 0..= '0' and f{i} <= '9': - j = j * 10 + ord(f{i}) - ord('0') - inc i - let idx = if not negative: j-1 else: args.len-j - r.add args[idx] - of '$': - inc(i) - r.add '$' - of '[': - let start = i+1 - while i < f.len and f{i} != ']': inc i - inc i - if i >= f.len: raiseInvalidFormat"']' expected" - case f{i} - of '#': - parseChoice(f, start, parseInt args[num], r) - inc i - inc num - of '1'..'9', '-': - var j = 0 - var negative = f{i} == '-' - if negative: inc i - while f{i} >= '0' and f{i} <= '9': - j = j * 10 + ord(f{i}) - ord('0') - inc i - let idx = if not negative: j-1 else: args.len-j - parseChoice(f, start, parseInt args[idx], r) - else: raiseInvalidFormat"argument index expected after ']'" - else: - raiseInvalidFormat("'#', '$', or number expected") - if i < f.len and f{i} == '$': inc i - else: - r.sadd f{i} - inc i - result = join(r) - - -when isMainModule: - addTranslation(Language.deDE, "$#$ -> $#$", "$2 macht $1") - setCurrentLanguage(Language.deDE) - - echo(i18n"$#$ -> $#$" % [cstring"1", "2"]) - echo(i18n"$[1:item |items ]1$ -> $1" % [cstring"1", "2"]) - echo(i18n"$[1:item |items ]1 -> $1" % [cstring"0", "2"]) - echo(i18n"$[1:item |items ]1 -> $1" % [cstring"2", "2"]) - echo(i18n"$[1:item |items ]1$ -> $1" % [cstring"3", "2"]) - echo(i18n"$1 $[1:item |4:huha |items ]1$ -> $1" % [cstring"4", "2"]) diff --git a/karax/jdict.nim b/karax/jdict.nim deleted file mode 100644 index c9e2224..0000000 --- a/karax/jdict.nim +++ /dev/null @@ -1,30 +0,0 @@ - -type - JDict*[K, V] = ref object - -proc `[]`*[K, V](d: JDict[K, V], k: K): V {.importcpp: "#[#]".} -proc `[]=`*[K, V](d: JDict[K, V], k: K, v: V) {.importcpp: "#[#] = #".} - -proc newJDict*[K, V](): JDict[K, V] {.importcpp: "{@}".} - -proc contains*[K, V](d: JDict[K, V], k: K): bool {.importcpp: "#.hasOwnProperty(#)".} - -proc del*[K, V](d: JDict[K, V], k: K) {.importcpp: "delete #[#]".} - -iterator keys*[K, V](d: JDict[K, V]): K = - var kkk: K - {.emit: ["for (", kkk, " in ", d, ") {"].} - yield kkk - {.emit: ["}"].} - -type - JSeq*[T] = ref object - -proc `[]`*[T](s: JSeq[T], i: int): T {.importcpp: "#[#]", noSideEffect.} -proc `[]=`*[T](s: JSeq[T], i: int, v: T) {.importcpp: "#[#] = #", noSideEffect.} - -proc newJSeq*[T](len: int = 0): JSeq[T] {.importcpp: "new Array(#)".} -proc len*[T](s: JSeq[T]): int {.importcpp: "#.length", noSideEffect.} -proc add*[T](s: JSeq[T]; x: T) {.importcpp: "#.push(#)", noSideEffect.} - -proc shrink*[T](s: JSeq[T]; shorterLen: int) {.importcpp: "#.length = #", noSideEffect.} diff --git a/karax/jjson.nim b/karax/jjson.nim deleted file mode 100644 index ad6106b..0000000 --- a/karax/jjson.nim +++ /dev/null @@ -1,67 +0,0 @@ -## This module implements some small zero-overhead 'JsonNode' type -## and helper that maps directly to JavaScript objects. - -type - JsonNode* {.importc.} = ref object - -proc `[]`*(obj: JsonNode; fieldname: cstring): JsonNode {.importcpp: "#[#]".} -proc `[]`*(obj: JsonNode; index: int): JsonNode {.importcpp: "#[#]".} -proc `[]=`*[T](obj: JsonNode; fieldname: cstring; value: T) - {.importcpp: "#[#] = #".} -proc length(x: JsonNode): int {.importcpp: "#.length".} -proc len*(x: JsonNode): int = (if x.isNil: 0 else: x.length) - -proc newJsonNode*(fields: varargs[(cstring, JsonNode)]): JsonNode = - result = JsonNode() - for f in fields: - result[f[0]] = f[1] - -proc newJObject*(): JsonNode = - result = JsonNode() - -proc newJArray*(elements: varargs[JsonNode]): JsonNode {.importcpp: "#".} - -proc newJNull*(): JsonNode = nil - -template `%`*(x: typed): JsonNode = cast[JsonNode](x) -template `%`*(x: string): JsonNode = cast[JsonNode](cstring x) - -proc getNum*(x: JsonNode): int {.importcpp: "#".} - -proc getInt*(x: JsonNode): int {.importcpp: "#".} -proc getStr*(x: JsonNode): cstring {.importcpp: "#".} -proc getFNum*(x: JsonNode): cstring {.importcpp: "#".} - -iterator items*(x: JsonNode): JsonNode = - for i in 0..= 0: - # result.key = n.key - for k, v in attrs(n): - if v != nil: - result.setAttr(k, v) - applyEvents(n) - if kxi != nil and n == kxi.toFocusV and kxi.toFocus.isNil: - kxi.toFocus = result - if not n.style.isNil: applyStyle(result, n.style) - -proc same(n: VNode, e: Node; nesting = 0): bool = - if kxi.orphans.contains(n.id): return true - if n.kind == VNodeKind.component: - result = same(VComponent(n).expanded, e, nesting+1) - elif n.kind == VNodeKind.verbatim: - result = true - elif n.kind == VNodeKind.vthunk or n.kind == VNodeKind.dthunk: - # we don't check these: - result = true - elif toTag[n.kind] == e.nodename: - result = true - if n.kind != VNodeKind.text: - # BUGFIX: Microsoft's Edge gives the textarea a child containing the text node! - if e.len != n.len and n.kind != VNodeKind.textarea: - echo "expected ", n.len, " real ", e.len, " ", toTag[n.kind], " nesting ", nesting - return false - for i in 0 ..< n.len: - if not same(n[i], e[i], nesting+1): return false - else: - echo "VDOM: ", toTag[n.kind], " DOM: ", e.nodename - -proc replaceById(id: cstring; newTree: Node) = - let x = document.getElementById(id) - x.parentNode.replaceChild(newTree, x) - newTree.id = id - -type - EqResult = enum - componentsIdentical, different, similar, identical, usenewNode - -when defined(profileKarax): - type - DifferEnum = enum - deKind, deId, deIndex, deText, deComponent, deClass, - deSimilar - - var - reasons: array[DifferEnum, int] - - proc echa(a: array[DifferEnum, int]) = - for i in low(DifferEnum)..high(DifferEnum): - echo i, " value: ", a[i] - -proc eq(a, b: VNode; recursive: bool): EqResult = - if a.kind != b.kind: - when defined(profileKarax): inc reasons[deKind] - return different - if a.id != b.id: - when defined(profileKarax): inc reasons[deId] - return different - result = identical - if a.index != b.index: - when defined(profileKarax): inc reasons[deIndex] - return different - if a.kind == VNodeKind.text: - if a.text != b.text: - when defined(profileKarax): inc reasons[deText] - return different # similar - elif a.kind == VNodeKind.vthunk: - if a.text != b.text: return different - if a.len != b.len: return different - for i in 0..>" & depth) - elif n.kind == VNodeKind.text: - kout depth, n.text - for i in 0 ..< n.len: - printV(n[i], depth & " ") - -proc addPatch(kxi: KaraxInstance; ka: PatchKind; parenta, currenta: Node; - na, oldNode: VNode) = - let L = kxi.patchLen - if L >= kxi.patches.len: - # allocate more space: - kxi.patches.add(Patch(k: ka, parent: parenta, current: currenta, - newNode: na, oldNode: oldNode)) - else: - kxi.patches[L].k = ka - kxi.patches[L].parent = parenta - kxi.patches[L].current = currenta - kxi.patches[L].newNode = na - kxi.patches[L].oldNode = oldNode - inc kxi.patchLen - -proc addPatchV(kxi: KaraxInstance; parent: VNode; pos: int; newChild: VNode) = - let L = kxi.patchLenV - if L >= kxi.patchesV.len: - # allocate more space: - kxi.patchesV.add(PatchV(parent: parent, newChild: newChild, pos: pos)) - else: - kxi.patchesV[L].parent = parent - kxi.patchesV[L].newChild = newChild - kxi.patchesV[L].pos = pos - inc kxi.patchLenV - -proc moveDom(dest, src: VNode) = - dest.dom = src.dom - src.dom = nil - if dest.id != nil: - kxi.byId[dest.id] = dest - assert dest.len == src.len - for i in 0.. We cannot ever use the old VDOM, we have to use the new virtual -# DOM. For identical nodes we need to take over the .dom field from the old -# node since we don't recompute them. This must be done recursively. In -# vnodeToDom we have to check whether the 'dom' field was already set. If so, -# There is nothing to do. -# "Similar" nodes can have the opposite effect; consider -# -# AAAABAAAA -# AAAACDAAAA -# -# In this example B did change to C and 'D' is new. However, replacing B by -# CD is fine. -# - - -proc diff(newNode, oldNode: VNode; parent, current: Node; kxi: KaraxInstance) = - when defined(stats): - if kxi.recursion > 100: - echo "newNode ", newNode.kind, " oldNode ", oldNode.kind, " eq ", eq(newNode, oldNode, false) - if oldNode.kind == VNodeKind.text: - echo oldNode.text - inc kxi.recursion - let result = eq(newNode, oldNode, false) - case result - of componentsIdentical: - kxi.components.add ComponentPair(oldNode: VComponent(oldNode), - newNode: VComponent(newNode), - parent: parent, - current: current) - of identical, similar: - newNode.dom = oldNode.dom - if result == similar: - updateStyles(newNode, oldNode) - updateAttributes(newNode, oldNode) - if oldNode.kind == VNodeKind.text: - oldNode.text = newNode.text - oldNode.dom.nodeValue = newNode.text - - if newNode.events.len != 0 or oldNode.events.len != 0: - mergeEvents(newNode, oldNode, kxi) - - let newLength = newNode.len - let oldLength = oldNode.len - if newLength == 0 and oldLength == 0: return - let minLength = min(newLength, oldLength) - - assert oldNode.kind == newNode.kind - var commonPrefix = 0 - - # compute common prefix: - while commonPrefix < minLength: - if eq(newNode[commonPrefix], oldNode[commonPrefix], true) == identical: - kxi.addPatch(pkSame, nil, nil, newNode[commonPrefix], oldNode[commonPrefix]) - inc commonPrefix - else: - break - - # compute common suffix: - var oldPos = oldLength - 1 - var newPos = newLength - 1 - while oldPos >= commonPrefix and newPos >= commonPrefix: - if eq(newNode[newPos], oldNode[oldPos], true) == identical: - kxi.addPatch(pkSame, nil, nil, newNode[newPos], oldNode[oldPos]) - dec oldPos - dec newPos - else: - break - - let pos = min(oldPos, newPos) + 1 - # now the different children are in commonPrefix .. pos - 1: - for i in commonPrefix..pos-1: - diff(newNode[i], oldNode[i], current, current.childNodes[i], kxi) - - if oldPos + 1 == oldLength: - for i in pos..newPos: - kxi.addPatch(pkAppend, current, nil, newNode[i], nil) - else: - let before = current.childNodes[oldPos + 1] - for i in pos..newPos: - kxi.addPatch(pkInsertBefore, current, before, newNode[i], nil) - # XXX call 'attach' here? - for i in pos..oldPos: - detach(oldNode[i]) - #doAssert i < current.childNodes.len - kxi.addPatch(pkRemove, current, current.childNodes[i], nil, nil) - of different: - detach(oldNode) - kxi.addPatch(pkReplace, parent, current, newNode, nil) - of usenewNode: doAssert(false, "eq returned usenewNode") - when defined(stats): - dec kxi.recursion - -proc applyComponents(kxi: KaraxInstance) = - # the first 'diff' pass detects components in the VDOM. The - # 'applyComponents' expands components and so on until no - # components are left to check. - var i = 0 - # beware: 'diff' appends to kxi.components! - # So this is actually a fixpoint iteration: - while i < kxi.components.len: - let x = kxi.components[i].oldNode - let newNode = kxi.components[i].newNode - when defined(karaxDebug): - echo "Processing component ", newNode.text, " changed impl set ", x.changedImpl != nil - if x.changedImpl != nil and x.changedImpl(x, newNode): - when defined(karaxDebug): - echo "Component ", newNode.text, " did change" - let current = kxi.components[i].current - let parent = kxi.components[i].parent - x.updatedImpl(x, newNode) - let oldExpanded = x.expanded - x.expanded = x.renderImpl(x) - when defined(karaxDebug): - echo "Component ", newNode.text, " re-rendered" - x.renderedVersion = x.version - if oldExpanded == nil: - detach(x) - kxi.addPatch(pkReplace, parent, current, x.expanded, nil) - when defined(karaxDebug): - echo "Component ", newNode.text, ": old expansion didn't exist" - else: - diff(x.expanded, oldExpanded, parent, current, kxi) - when false: - if res == usenewNode: - when defined(karaxDebug): - echo "Component ", newNode.text, ": re-render triggered a DOM change (case A)" - discard "diff created a patchset for us, so this is fine" - elif res != different: - when defined(karaxDebug): - echo "Component ", newNode.text, ": re-render triggered no DOM change whatsoever" - x.expanded = oldExpanded - assert oldExpanded.dom != nil, "old expanded.dom is nil" - else: - when defined(karaxDebug): - echo "Component ", newNode.text, ": re-render triggered a DOM change (case B)" - assert x.expanded.dom != nil, "expanded.dom is nil" - inc i - setLen(kxi.components, 0) - -when defined(stats): - proc depth(n: VNode; total: var int): int = - var m = 0 - for i in 0..= parent.len: - kxi.addPatch(pkAppend, current, nil, kid, nil) - parent.add(kid) - else: - let before = current.childNodes[position] - kxi.addPatch(pkInsertBefore, current, before, kid, nil) - parent.insert(kid, position) - applyPatch(kxi) - doAssert same(kxi.currentTree, document.getElementById(kxi.rootId)) - -proc runDiff*(kxi: KaraxInstance; oldNode, newNode: VNode) = - let olddom = oldNode.dom - doAssert olddom != nil - diff(newNode, oldNode, nil, olddom, kxi) - # this is a bit nasty: Since we cannot patch the 'parent' of - # the current VNode (because we don't store it at all!), we - # need to override the fields individually: - takeOverFields(newNode, oldNode) - applyComponents(kxi) - applyPatch(kxi) - if kxi.currentTree == oldNode: - kxi.currentTree = newNode - doAssert same(kxi.currentTree, document.getElementById(kxi.rootId)) - -var onhashChange {.importc: "window.onhashchange".}: proc() -var hashPart {.importc: "window.location.hash".}: cstring - -proc avoidDomDiffing*(kxi: KaraxInstance = kxi) = - ## enforce a full redraw for the next redraw operation. - ## This can be used as a temporary way to workaround DOM diffing - ## problems or to avoid the DOM diffing when you already know - ## it should use a completely new DOM. - ## This is an experimental API. - kxi.currentTree = nil - -proc reqFrame(callback: proc()): int {.importc: "window.requestAnimationFrame".} -when false: - proc cancelFrame(id: int) {.importc: "window.cancelAnimationFrame".} - -proc dodraw(kxi: KaraxInstance) = - if kxi.renderer.isNil: return - kxi.renderId = 0 - - if kxi.rendering: - # there is a render already running, delay 1 frame - kxi.renderId = reqFrame(proc () = kxi.dodraw) - return - - kxi.rendering = true - - let rdata = RouterData(hashPart: hashPart) - let newtree = kxi.renderer(rdata) - inc kxi.runCount - newtree.id = kxi.rootId - kxi.toFocus = nil - if kxi.currentTree == nil: - let asdom = toDom(newtree, useAttachedNode = true, kxi) - replaceById(kxi.rootId, asdom) - else: - doAssert same(kxi.currentTree, document.getElementById(kxi.rootId)) - let olddom = document.getElementById(kxi.rootId) - diff(newtree, kxi.currentTree, nil, olddom, kxi) - when defined(profileKarax): - echo "<<<<<<<<<<<<<<" - echa reasons - applyComponents(kxi) - when defined(profileKarax): - echo "--------------" - echa reasons - echo ">>>>>>>>>>>>>>" - applyPatch(kxi) - kxi.currentTree = newtree - doAssert same(kxi.currentTree, document.getElementById(kxi.rootId)) - - if not kxi.postRenderCallback.isNil: - kxi.postRenderCallback(rdata) - - # now that it's part of the DOM, give it the focus: - if kxi.toFocus != nil: - kxi.toFocus.focus() - kxi.rendering = false - when defined(stats): - kxi.recursion = 0 - var total = 0 - echo "depth ", depth(kxi.currentTree, total), " total ", total - -proc redraw*(kxi: KaraxInstance = kxi) = - # we buffer redraw requests: - when false: - if drawTimeout != nil: - clearTimeout(drawTimeout) - drawTimeout = setTimeout(dodraw, 30) - elif true: - if kxi.renderId == 0: - kxi.renderId = reqFrame(proc () = kxi.dodraw) - else: - dodraw(kxi) - -proc redrawSync*(kxi: KaraxInstance = kxi) = dodraw(kxi) - -proc init(ev: Event) = - kxi.renderId = reqFrame(proc () = kxi.dodraw) - -proc setRenderer*(renderer: proc (data: RouterData): VNode, - root: cstring = "ROOT", - clientPostRenderCallback: - proc (data: RouterData) = nil): KaraxInstance {. - discardable.} = - ## Setup Karax. Usually the return value can be ignored. - if document.getElementById(root).isNil: - let msg = "Could not find a
with id=" & root & - ". Karax needs it as its rendering target." - raise newException(Exception, $msg) - - result = KaraxInstance(rootId: root, renderer: renderer, - postRenderCallback: clientPostRenderCallback, - patches: newSeq[Patch](60), - patchesV: newSeq[PatchV](30), - components: @[], - surpressRedraws: false, - byId: newJDict[cstring, VNode](), - orphans: newJDict[cstring, bool]()) - kxi = result - window.onload = init - onhashChange = proc() = redraw() - -proc setRenderer*(renderer: proc (): VNode, root: cstring = "ROOT", - clientPostRenderCallback: proc () = nil): KaraxInstance {.discardable.} = - ## Setup Karax. Usually the return value can be ignored. - proc wrapRenderer(data: RouterData): VNode = result = renderer() - proc wrapPostRender(data: RouterData) = - if clientPostRenderCallback != nil: clientPostRenderCallback() - setRenderer(wrapRenderer, root, wrapPostRender) - -proc setInitializer*(renderer: proc (data: RouterData): VNode, root: cstring = "ROOT", - clientPostRenderCallback: - proc (data: RouterData) = nil): KaraxInstance {.discardable.} = - ## Setup Karax. Usually the return value can be ignored. - result = KaraxInstance(rootId: root, renderer: renderer, - postRenderCallback: clientPostRenderCallback, - patches: newSeq[Patch](60), - patchesV: newSeq[PatchV](30), - components: @[], - surpressRedraws: true, - byId: newJDict[cstring, VNode](), - orphans: newJDict[cstring, bool]()) - kxi = result - window.onload = init - -proc addEventHandler*(n: VNode; k: EventKind; action: EventHandler; - kxi: KaraxInstance = kxi) = - ## Implements the foundation of Karax's event management. - ## Karax DSL transforms ``tag(onEvent = handler)`` to - ## ``tempNode.addEventHandler(tagNode, EventKind.onEvent, wrapper)`` - ## where ``wrapper`` calls the passed ``action`` and then triggers - ## a ``redraw``. - proc wrapper(ev: Event; n: VNode) = - action(ev, n) - if not kxi.surpressRedraws: redraw(kxi) - addEventListener(n, k, wrapper) - -proc addEventHandler*(n: VNode; k: EventKind; action: proc(); - kxi: KaraxInstance = kxi) = - ## Implements the foundation of Karax's event management. - ## Karax DSL transforms ``tag(onEvent = handler)`` to - ## ``tempNode.addEventHandler(tagNode, EventKind.onEvent, wrapper)`` - ## where ``wrapper`` calls the passed ``action`` and then triggers - ## a ``redraw``. - proc wrapper(ev: Event; n: VNode) = - action() - if not kxi.surpressRedraws: redraw(kxi) - addEventListener(n, k, wrapper) - -proc setOnHashChange*(action: proc (hashPart: cstring)) {.deprecated: "use setRenderer instead".} = - ## Now deprecated, instead pass a callback to ``setRenderer`` that receives - ## a ``data: RouterData`` parameter. - proc wrapper() = - action(hashPart) - redraw() - onhashchange = wrapper - -proc setForeignNodeId*(id: cstring; kxi: KaraxInstance = kxi) = - ## Declares a node ID as "foreign". Foreign nodes are not - ## under Karax's control in the sense that Karax does not attempt - ## to perform structural checks on them. - kxi.orphans[id] = true - -{.push stackTrace:off.} -proc setupErrorHandler*() = - ## Installs an error handler that transforms native JS unhandled - ## exceptions into Nim based stack traces. If `useAlert` is false, - ## the error message is put into the console, otherwise `alert` - ## is called. - proc stackTraceAsCstring(): cstring = cstring(getStackTrace()) - var onerror {.importc: "window.onerror", used.} = - proc (msg, url: cstring, line, col: int, error: cstring): bool = - var x = cstring"Error: " & msg & "\n" & stackTraceAsCstring() - echo(x) - return true # suppressErrorAlert -{.pop.} - -proc prepend(parent, kid: Element) = - parent.insertBefore(kid, parent.firstChild) - -proc loadScript*(jsfilename: cstring; kxi: KaraxInstance = kxi) = - let s = document.createElement("script") - s.setAttr "type", "text/javascript" - s.setAttr "src", jsfilename - document.body.prepend(s) - redraw(kxi) - -proc runLater*(action: proc(); later = 400): Timeout {.discardable.} = - proc wrapper() = - action() - redraw() - result = setTimeout(wrapper, later) - -proc setInputText*(n: VNode; s: cstring) = - ## Sets the text of input elements. - n.text = s - if n.dom != nil: n.dom.value = s - -proc getInputText*(n: VNode): cstring = - if n.dom != nil: - result = n.dom.value - -proc toChecked*(checked: bool): cstring = - (if checked: cstring"checked" else: cstring(nil)) - -proc toDisabled*(disabled: bool): cstring = - (if disabled: cstring"disabled" else: cstring(nil)) - -proc toSelected*(selected: bool): cstring = - (if selected: cstring"selected" else: cstring(nil)) - -proc vnodeToDom*(n: VNode; kxi: KaraxInstance = nil): Node = - result = toDom(n, useAttachedNode = false, kxi) diff --git a/karax/kbase.nim b/karax/kbase.nim deleted file mode 100644 index 1a0cb93..0000000 --- a/karax/kbase.nim +++ /dev/null @@ -1,8 +0,0 @@ -## Karax -- Single page applications for Nim. - -## Basic type definitions for Karax. -when defined(js): - type kstring* = cstring -else: - type kstring* = string - diff --git a/karax/kdom.nim b/karax/kdom.nim deleted file mode 100644 index 782d825..0000000 --- a/karax/kdom.nim +++ /dev/null @@ -1,10 +0,0 @@ -## Karax -- Single page applications for Nim. - -from dom import nil - -when not declared(dom.DomApiVersion): - include kdom_impl - -else: - import dom - export dom diff --git a/karax/kdom_impl.nim b/karax/kdom_impl.nim deleted file mode 100644 index aaa26cb..0000000 --- a/karax/kdom_impl.nim +++ /dev/null @@ -1,1232 +0,0 @@ -# -# -# Nim's Runtime Library -# (c) Copyright 2012 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -## Declaration of the Document Object Model for the `JavaScript backend -## `_. - -when not defined(js) and not defined(Nimdoc): - {.error: "This module only works on the JavaScript platform".} - -type - EventTarget* = ref EventTargetObj - EventTargetObj {.importc.} = object of RootObj - onabort*: proc (event: Event) {.nimcall.} - onblur*: proc (event: Event) {.nimcall.} - onchange*: proc (event: Event) {.nimcall.} - onclick*: proc (event: Event) {.nimcall.} - ondblclick*: proc (event: Event) {.nimcall.} - onerror*: proc (event: Event) {.nimcall.} - onfocus*: proc (event: Event) {.nimcall.} - onkeydown*: proc (event: Event) {.nimcall.} - onkeypress*: proc (event: Event) {.nimcall.} - onkeyup*: proc (event: Event) {.nimcall.} - onload*: proc (event: Event) {.nimcall.} - onmousedown*: proc (event: Event) {.nimcall.} - onmousemove*: proc (event: Event) {.nimcall.} - onmouseout*: proc (event: Event) {.nimcall.} - onmouseover*: proc (event: Event) {.nimcall.} - onmouseup*: proc (event: Event) {.nimcall.} - onreset*: proc (event: Event) {.nimcall.} - onselect*: proc (event: Event) {.nimcall.} - onsubmit*: proc (event: Event) {.nimcall.} - onunload*: proc (event: Event) {.nimcall.} - - # https://developer.mozilla.org/en-US/docs/Web/Events - DomEvent* {.pure.} = enum - Abort = "abort", - BeforeInput = "beforeinput", - Blur = "blur", - Click = "click", - CompositionEnd = "compositionend", - CompositionStart = "compositionstart", - CompositionUpdate = "compositionupdate", - DblClick = "dblclick", - Error = "error", - Focus = "focus", - FocusIn = "focusin", - FocusOut = "focusout", - Input = "input", - KeyDown = "keydown", - KeyPress = "keypress", - KeyUp = "keyup", - Load = "load", - MouseDown = "mousedown", - MouseEnter = "mouseenter", - MouseLeave = "mouseleave", - MouseMove = "mousemove", - MouseOut = "mouseout", - MouseOver = "mouseover", - MouseUp = "mouseup", - Resize = "resize", - Scroll = "scroll", - Select = "select", - Unload = "unload", - Wheel = "wheel" - - Window* = ref WindowObj - WindowObj {.importc.} = object of EventTargetObj - document*: Document - event*: Event - history*: History - location*: Location - closed*: bool - defaultStatus*: cstring - innerHeight*, innerWidth*: int - locationbar*: ref LocationBar - menubar*: ref MenuBar - name*: cstring - outerHeight*, outerWidth*: int - pageXOffset*, pageYOffset*: int - personalbar*: ref PersonalBar - scrollbars*: ref ScrollBars - statusbar*: ref StatusBar - status*: cstring - toolbar*: ref ToolBar - frames*: seq[Frame] - screen*: Screen - - Frame* = ref FrameObj - FrameObj {.importc.} = object of WindowObj - - ClassList* = ref ClassListObj - ClassListObj {.importc.} = object of RootObj - - NodeType* = enum - ElementNode = 1, - AttributeNode, - TextNode, - CDATANode, - EntityRefNode, - EntityNode, - ProcessingInstructionNode, - CommentNode, - DocumentNode, - DocumentTypeNode, - DocumentFragmentNode, - NotationNode - - Node* = ref NodeObj - NodeObj {.importc.} = object of EventTargetObj - attributes*: seq[Node] - childNodes*: seq[Node] - children*: seq[Node] - data*: cstring - firstChild*: Node - lastChild*: Node - nextSibling*: Node - nodeName*: cstring - nodeType*: NodeType - nodeValue*: cstring - parentNode*: Node - previousSibling*: Node - innerHTML*: cstring - style*: Style - when defined(nodejs): - id*: cstring - - Document* = ref DocumentObj - DocumentObj {.importc.} = object of NodeObj - alinkColor*: cstring - bgColor*: cstring - body*: Element - charset*: cstring - cookie*: cstring - defaultCharset*: cstring - fgColor*: cstring - head*: Element - lastModified*: cstring - linkColor*: cstring - referrer*: cstring - title*: cstring - URL*: cstring - vlinkColor*: cstring - anchors*: seq[AnchorElement] - forms*: seq[FormElement] - images*: seq[ImageElement] - applets*: seq[Element] - embeds*: seq[EmbedElement] - links*: seq[LinkElement] - - Element* = ref ElementObj - ElementObj {.importc.} = object of NodeObj - classList*: Classlist - checked*: bool - defaultChecked*: bool - defaultValue*: cstring - disabled*: bool - form*: FormElement - name*: cstring - readOnly*: bool - options*: seq[OptionElement] - selectedOptions*: seq[OptionElement] - clientWidth*, clientHeight*: int - contentEditable*: string - isContentEditable*: bool - dir*: string - offsetHeight*: int - offsetWidth*: int - offsetLeft*: int - offsetTop*: int - - # https://developer.mozilla.org/en-US/docs/Web/API/ValidityState - ValidityState* = ref ValidityStateObj - ValidityStateObj {.importc.} = object - badInput*: bool - customError*: bool - patternMismatch*: bool - rangeOverflow*: bool - rangeUnderflow*: bool - stepMismatch*: bool - tooLong*: bool - tooShort*: bool - typeMismatch*: bool - valid*: bool - valueMissing*: bool - - # https://developer.mozilla.org/en-US/docs/Web/API/Blob - Blob* = ref BlobObj - BlobObj {.importc.} = object of RootObj - size*: int - `type`*: cstring - - # https://developer.mozilla.org/en-US/docs/Web/API/File - File* = ref FileObj - FileObj {.importc.} = object of Blob - lastModified*: int - name*: cstring - - # https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement - InputElement* = ref InputElementObj - InputElementObj {.importc.} = object of Element - # Properties related to the parent form - formAction*: cstring - formEncType*: cstring - formMethod*: cstring - formNoValidate*: bool - formTarget*: cstring - - # Properties that apply to any type of input element that is not hidden - `type`*: cstring - autofocus*: bool - required*: bool - value*: cstring - validity*: ValidityState - validationMessage*: cstring - willValidate*: bool - - # Properties that apply only to elements of type "checkbox" or "radio" - indeterminate*: bool - - # Properties that apply only to elements of type "image" - alt*: cstring - height*: cstring - src*: cstring - width*: cstring - - # Properties that apply only to elements of type "file" - accept*: cstring - files*: seq[Blob] - - # Properties that apply only to text/number-containing or elements - autocomplete*: cstring - maxLength*: int - size*: int - pattern*: cstring - placeholder*: cstring - min*: cstring - max*: cstring - selectionStart*: int - selectionEnd*: int - selectionDirection*: cstring - - # Properties not yet categorized - dirName*: cstring - accessKey*: cstring - list*: Element - multiple*: bool - labels*: seq[Element] - step*: cstring - valueAsDate*: cstring - valueAsNumber*: float - - LinkElement* = ref LinkObj - LinkObj {.importc.} = object of ElementObj - target*: cstring - text*: cstring - x*: int - y*: int - - EmbedElement* = ref EmbedObj - EmbedObj {.importc.} = object of ElementObj - height*: int - hspace*: int - src*: cstring - width*: int - `type`*: cstring - vspace*: int - - AnchorElement* = ref AnchorObj - AnchorObj {.importc.} = object of ElementObj - text*: cstring - x*, y*: int - - OptionElement* = ref OptionObj - OptionObj {.importc.} = object of ElementObj - defaultSelected*: bool - selected*: bool - selectedIndex*: int - text*: cstring - value*: cstring - - # https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement - FormElement* = ref FormObj - FormObj {.importc.} = object of ElementObj - acceptCharset*: cstring - action*: cstring - autocomplete*: cstring - elements*: seq[Element] - encoding*: cstring - enctype*: cstring - length*: int - `method`*: cstring - noValidate*: bool - target*: cstring - - ImageElement* = ref ImageObj - ImageObj {.importc.} = object of ElementObj - border*: int - complete*: bool - height*: int - hspace*: int - lowsrc*: cstring - src*: cstring - vspace*: int - width*: int - - Style* = ref StyleObj - StyleObj {.importc.} = object of RootObj - background*: cstring - backgroundAttachment*: cstring - backgroundColor*: cstring - backgroundImage*: cstring - backgroundPosition*: cstring - backgroundRepeat*: cstring - border*: cstring - borderBottom*: cstring - borderBottomColor*: cstring - borderBottomStyle*: cstring - borderBottomWidth*: cstring - borderColor*: cstring - borderLeft*: cstring - borderLeftColor*: cstring - borderLeftStyle*: cstring - borderLeftWidth*: cstring - borderRight*: cstring - borderRightColor*: cstring - borderRightStyle*: cstring - borderRightWidth*: cstring - borderStyle*: cstring - borderTop*: cstring - borderTopColor*: cstring - borderTopStyle*: cstring - borderTopWidth*: cstring - borderWidth*: cstring - bottom*: cstring - captionSide*: cstring - clear*: cstring - clip*: cstring - color*: cstring - cursor*: cstring - direction*: cstring - display*: cstring - emptyCells*: cstring - cssFloat*: cstring - font*: cstring - fontFamily*: cstring - fontSize*: cstring - fontStretch*: cstring - fontStyle*: cstring - fontVariant*: cstring - fontWeight*: cstring - height*: cstring - left*: cstring - letterSpacing*: cstring - lineHeight*: cstring - listStyle*: cstring - listStyleImage*: cstring - listStylePosition*: cstring - listStyleType*: cstring - margin*: cstring - marginBottom*: cstring - marginLeft*: cstring - marginRight*: cstring - marginTop*: cstring - maxHeight*: cstring - maxWidth*: cstring - minHeight*: cstring - minWidth*: cstring - overflow*: cstring - padding*: cstring - paddingBottom*: cstring - paddingLeft*: cstring - paddingRight*: cstring - paddingTop*: cstring - pageBreakAfter*: cstring - pageBreakBefore*: cstring - pointerEvents*: cstring - position*: cstring - right*: cstring - scrollbar3dLightColor*: cstring - scrollbarArrowColor*: cstring - scrollbarBaseColor*: cstring - scrollbarDarkshadowColor*: cstring - scrollbarFaceColor*: cstring - scrollbarHighlightColor*: cstring - scrollbarShadowColor*: cstring - scrollbarTrackColor*: cstring - tableLayout*: cstring - textAlign*: cstring - textDecoration*: cstring - textIndent*: cstring - textTransform*: cstring - transform*: cstring - top*: cstring - verticalAlign*: cstring - visibility*: cstring - width*: cstring - wordSpacing*: cstring - zIndex*: int - - EventPhase* = enum - None = 0, - CapturingPhase, - AtTarget, - BubblingPhase - - # https://developer.mozilla.org/en-US/docs/Web/API/Event - Event* = ref EventObj - EventObj {.importc.} = object of RootObj - bubbles*: bool - cancelBubble*: bool - cancelable*: bool - composed*: bool - currentTarget*: Node - defaultPrevented*: bool - eventPhase*: int - target*: Node - `type`*: cstring - isTrusted*: bool - - # https://developer.mozilla.org/en-US/docs/Web/API/UIEvent - UIEvent* = ref UIEventObj - UIEventObj {.importc.} = object of Event - detail*: int64 - view*: Window - - # https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent - KeyboardEvent* = ref KeyboardEventObj - KeyboardEventObj {.importc.} = object of UIEvent - altKey*, ctrlKey*, metaKey*, shiftKey*: bool - code*: cstring - isComposing*: bool - key*: cstring - keyCode*: int - location*: int - - # https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values - KeyboardEventKey* {.pure.} = enum - # Modifier keys - Alt, - AltGraph, - CapsLock, - Control, - Fn, - FnLock, - Hyper, - Meta, - NumLock, - ScrollLock, - Shift, - Super, - Symbol, - SymbolLock, - - # Whitespace keys - ArrowDown, - ArrowLeft, - ArrowRight, - ArrowUp, - End, - Home, - PageDown, - PageUp, - - # Editing keys - Backspace, - Clear, - Copy, - CrSel, - Cut, - Delete, - EraseEof, - ExSel, - Insert, - Paste, - Redo, - Undo, - - # UI keys - Accept, - Again, - Attn, - Cancel, - ContextMenu, - Escape, - Execute, - Find, - Finish, - Help, - Pause, - Play, - Props, - Select, - ZoomIn, - ZoomOut, - - # Device keys - BrigtnessDown, - BrigtnessUp, - Eject, - LogOff, - Power, - PowerOff, - PrintScreen, - Hibernate, - Standby, - WakeUp, - - # Common IME keys - AllCandidates, - Alphanumeric, - CodeInput, - Compose, - Convert, - Dead, - FinalMode, - GroupFirst, - GroupLast, - GroupNext, - GroupPrevious, - ModeChange, - NextCandidate, - NonConvert, - PreviousCandidate, - Process, - SingleCandidate, - - # Korean keyboards only - HangulMode, - HanjaMode, - JunjaMode, - - # Japanese keyboards only - Eisu, - Hankaku, - Hiragana, - HiraganaKatakana, - KanaMode, - KanjiMode, - Katakana, - Romaji, - Zenkaku, - ZenkakuHanaku, - - # Function keys - F1, - F2, - F3, - F4, - F5, - F6, - F7, - F8, - F9, - F10, - F11, - F12, - F13, - F14, - F15, - F16, - F17, - F18, - F19, - F20, - Soft1, - Soft2, - Soft3, - Soft4, - - # Phone keys - AppSwitch, - Call, - Camera, - CameraFocus, - EndCall, - GoBack, - GoHome, - HeadsetHook, - LastNumberRedial, - Notification, - MannerMode, - VoiceDial, - - # Multimedia keys - ChannelDown, - ChannelUp, - MediaFastForward, - MediaPause, - MediaPlay, - MediaPlayPause, - MediaRecord, - MediaRewind, - MediaStop, - MediaTrackNext, - MediaTrackPrevious, - - # Audio control keys - AudioBalanceLeft, - AudioBalanceRight, - AudioBassDown, - AudioBassBoostDown, - AudioBassBoostToggle, - AudioBassBoostUp, - AudioBassUp, - AudioFaderFront, - AudioFaderRear, - AudioSurroundModeNext, - AudioTrebleDown, - AudioTrebleUp, - AudioVolumeDown, - AUdioVolumeMute, - AudioVolumeUp, - MicrophoneToggle, - MicrophoneVolumeDown, - MicrophoneVolumeMute, - MicrophoneVolumeUp, - - # TV control keys - TV, - TV3DMode, - TVAntennaCable, - TVAudioDescription, - TVAudioDescriptionMixDown, - TVAudioDescriptionMixUp, - TVContentsMenu, - TVDataService, - TVInput, - TVInputComponent1, - TVInputComponent2, - TVInputComposite1, - TVInputComposite2, - TVInputHDMI1, - TVInputHDMI2, - TVInputHDMI3, - TVInputHDMI4, - TVInputVGA1, - TVMediaContext, - TVNetwork, - TVNumberEntry, - TVPower, - TVRadioService, - TVSatellite, - TVSatelliteBS, - TVSatelliteCS, - TVSatelliteToggle, - TVTerrestrialAnalog, - TVTerrestrialDigital, - TVTimer, - - # Media controller keys - AVRInput, - AVRPower, - ColorF0Red, - ColorF1Green, - ColorF2Yellow, - ColorF3Blue, - ColorF4Grey, - ColorF5Brown, - ClosedCaptionToggle, - Dimmer, - DisplaySwap, - DVR, - Exit, - FavoriteClear0, - FavoriteClear1, - FavoriteClear2, - FavoriteClear3, - FavoriteRecall0, - FavoriteRecall1, - FavoriteRecall2, - FavoriteRecall3, - FavoriteStore0, - FavoriteStore1, - FavoriteStore2, - FavoriteStore3, - Guide, - GuideNextDay, - GuidePreviousDay, - Info, - InstantReplay, - Link, - ListProgram, - LiveContent, - Lock, - MediaApps, - MediaAudioTrack, - MediaLast, - MediaSkipBackward, - MediaSkipForward, - MediaStepBackward, - MediaStepForward, - MediaTopMenu, - NavigateIn, - NavigateNext, - NavigateOut, - NavigatePrevious, - NextFavoriteChannel, - NextUserProfile, - OnDemand, - Pairing, - PinPDown, - PinPMove, - PinPUp, - PlaySpeedDown, - PlaySpeedReset, - PlaySpeedUp, - RandomToggle, - RcLowBattery, - RecordSpeedNext, - RfBypass, - ScanChannelsToggle, - ScreenModeNext, - Settings, - SplitScreenToggle, - STBInput, - STBPower, - Subtitle, - Teletext, - VideoModeNext, - Wink, - ZoomToggle, - - # Speech recognition keys - SpeechCorrectionList, - SpeechInputToggle, - - # Document keys - Close, - New, - Open, - Print, - Save, - SpellCheck, - MailForward, - MailReply, - MailSend, - - # Application selector keys - LaunchCalculator, - LaunchCalendar, - LaunchContacts, - LaunchMail, - LaunchMediaPlayer, - LaunchMusicPlayer, - LaunchMyComputer, - LaunchPhone, - LaunchScreenSaver, - LaunchSpreadsheet, - LaunchWebBrowser, - LaunchWebCam, - LaunchWordProcessor, - LaunchApplication1, - LaunchApplication2, - LaunchApplication3, - LaunchApplication4, - LaunchApplication5, - LaunchApplication6, - LaunchApplication7, - LaunchApplication8, - LaunchApplication9, - LaunchApplication10, - LaunchApplication11, - LaunchApplication12, - LaunchApplication13, - LaunchApplication14, - LaunchApplication15, - LaunchApplication16, - - # Browser control keys - BrowserBack, - BrowserFavorites, - BrowserForward, - BrowserHome, - BrowserRefresh, - BrowserSearch, - BrowserStop, - - # Numeric keypad keys - Key11, - Key12, - Separator - - MouseButtons* = enum - NoButton = 0, - PrimaryButton = 1, - SecondaryButton = 2, - AuxilaryButton = 4, - FourthButton = 8, - FifthButton = 16 - - # https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent - MouseEvent* = ref MouseEventObj - MouseEventObj {.importc.} = object of UIEvent - altKey*, ctrlKey*, metaKey*, shiftKey*: bool - button*: int - buttons*: int - clientX*, clientY*: int - movementX*, movementY*: int - offsetX*, offsetY*: int - pageX*, pageY*: int - relatedTarget*: EventTarget - #region*: cstring - screenX*, screenY*: int - x*, y*: int - - DataTransferItemKind* {.pure.} = enum - File = "file", - String = "string" - - # https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem - DataTransferItem* = ref DataTransferItemObj - DataTransferItemObj {.importc.} = object of RootObj - kind*: cstring - `type`*: cstring - - # https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer - DataTransfer* = ref DataTransferObj - DataTransferObj {.importc.} = object of RootObj - dropEffect*: cstring - effectAllowed*: cstring - files*: seq[Element] - items*: seq[DataTransferItem] - types*: seq[cstring] - - DataTransferDropEffect* {.pure.} = enum - None = "none", - Copy = "copy", - Link = "link", - Move = "move" - - DataTransferEffectAllowed* {.pure.} = enum - None = "none", - Copy = "copy", - CopyLink = "copyLink", - CopyMove = "copyMove", - Link = "link", - LinkMove = "linkMove", - Move = "move", - All = "all", - Uninitialized = "uninitialized" - - DragEventTypes* = enum - Drag = "drag", - DragEnd = "dragend", - DragEnter = "dragenter", - DragExit = "dragexit", - DragLeave = "dragleave", - DragOver = "dragover", - DragStart = "dragstart", - Drop = "drop" - - # https://developer.mozilla.org/en-US/docs/Web/API/DragEvent - DragEvent* {.importc.} = object of MouseEvent - dataTransfer*: DataTransfer - - TouchList* {.importc.} = ref object of RootObj - length*: int - - Touch* = ref TouchObj - TouchObj {.importc.} = object of RootObj - identifier*: int - screenX*, screenY*, clientX*, clientY*, pageX*, pageY*: int - target*: Element - radiusX*, radiusY*: int - rotationAngle*: int - force*: float - - TouchEvent* = ref TouchEventObj - TouchEventObj {.importc.} = object of UIEvent - changedTouches*, targetTouches*, touches*: seq[Touch] - - Location* = ref LocationObj - LocationObj {.importc.} = object of RootObj - hash*: cstring - host*: cstring - hostname*: cstring - href*: cstring - pathname*: cstring - port*: cstring - protocol*: cstring - search*: cstring - - History* = ref HistoryObj - HistoryObj {.importc.} = object of RootObj - length*: int - - Navigator* = ref NavigatorObj - NavigatorObj {.importc.} = object of RootObj - appCodeName*: cstring - appName*: cstring - appVersion*: cstring - cookieEnabled*: bool - language*: cstring - platform*: cstring - userAgent*: cstring - mimeTypes*: seq[ref MimeType] - - Plugin* {.importc.} = object of RootObj - description*: cstring - filename*: cstring - name*: cstring - - MimeType* {.importc.} = object of RootObj - description*: cstring - enabledPlugin*: ref Plugin - suffixes*: seq[cstring] - `type`*: cstring - - LocationBar* {.importc.} = object of RootObj - visible*: bool - MenuBar* = LocationBar - PersonalBar* = LocationBar - ScrollBars* = LocationBar - ToolBar* = LocationBar - StatusBar* = LocationBar - - Screen = ref ScreenObj - ScreenObj {.importc.} = object of RootObj - availHeight*: int - availWidth*: int - colorDepth*: int - height*: int - pixelDepth*: int - width*: int - - TimeOut* {.importc.} = ref object of RootObj - Interval* {.importc.} = object of RootObj - - AddEventListenerOptions* = object - capture*: bool - once*: bool - passive*: bool - -when defined(nodejs): - # we provide a dummy DOM for nodejs for testing purposes - proc len*(x: Node): int = x.childNodes.len - proc `[]`*(x: Node; idx: int): Element = - assert idx >= 0 and idx < x.childNodes.len - result = cast[Element](x.childNodes[idx]) - - var document* = Document(nodeType: DocumentNode) - - proc getElem(x: Element; id: cstring): Element = - if x.id == id: return x - for i in 0..= 0 and rect.left >= 0 and - rect.bottom <= clientHeight().float and - rect.right <= clientWidth().float - -proc scrollTop*(e: Node): int {.importcpp: "#.scrollTop", nodecl.} -proc offsetHeight*(e: Node): int {.importcpp: "#.offsetHeight", nodecl.} -proc offsetTop*(e: Node): int {.importcpp: "#.offsetTop", nodecl.} -proc offsetLeft*(e: Node): int {.importcpp: "#.offsetLeft", nodecl.} diff --git a/karax/languages.nim b/karax/languages.nim deleted file mode 100644 index 6b6b027..0000000 --- a/karax/languages.nim +++ /dev/null @@ -1,616 +0,0 @@ -## Karax -- Single page applications for Nim. - -type - Language* {.pure.} = enum ## A pure enum that contains most (all?) - ## known human languages in current use. - afZA ## "South Africa - Afrikaans" - amET ## "Ethiopia - Amharic" - arAE ## "U.A.E. - Arabic" - arBH ## "Bahrain - Arabic" - arDZ ## "Algeria - Arabic" - arEG ## "Egypt - Arabic" - arIQ ## "Iraq - Arabic" - arJO ## "Jordan - Arabic" - arKW ## "Kuwait - Arabic" - arLB ## "Lebanon - Arabic" - arLY ## "Libya - Arabic" - arMA ## "Morocco - Arabic" - arOM ## "Oman - Arabic" - arQA ## "Qatar - Arabic" - arSA ## "Saudi Arabia - Arabic" - arSY ## "Syria - Arabic" - arTN ## "Tunisia - Arabic" - arYE ## "Yemen - Arabic" - arnCL ## "Chile - Mapudungun" - asIN ## "India - Assamese" - azAZ ## "Azerbaijan - Azeri (Cyrillic)" - baRU ## "Russia - Bashkir" - beBY ## "Belarus - Belarusian" - bgBG ## "Bulgaria - Bulgarian" - bnBD ## "Bangladesh - Bengali" - bnIN ## "India - Bengali" - boCN ## "People's Republic of China - Tibetan" - brFR ## "France - Breton" - bsBA ## "Bosnia and Herzegovina - Bosnian (Cyrillic)" - caES ## "Spain - Catalan" - coFR ## "France - Corsican" - csCZ ## "Czech Republic - Czech" - cyGB ## "United Kingdom - Welsh" - daDK ## "Denmark - Danish" - deAT ## "Austria - German" - deCH ## "Switzerland - German" - deDE ## "Germany - German" - deLI ## "Liechtenstein - German" - deLU ## "Luxembourg - German" - dsbDE ## "Germany - Lower Sorbian" - dvMV ## "Maldives - Divehi" - elGR ## "Greece - Greek" - en029 ## "Caribbean - English" - enAU ## "Australia - English" - enBZ ## "Belize - English" - enCA ## "Canada - English" - enGB ## "United Kingdom - English" - enIE ## "Ireland - English" - enIN ## "India - English" - enJM ## "Jamaica - English" - enMY ## "Malaysia - English" - enNZ ## "New Zealand - English" - enPH ## "Republic of the Philippines - English" - enSG ## "Singapore - English" - enTT ## "Trinidad and Tobago - English" - enUS ## "United States - English" - enZA ## "South Africa - English" - enZW ## "Zimbabwe - English" - esAR ## "Argentina - Spanish" - esBO ## "Bolivia - Spanish" - esCL ## "Chile - Spanish" - esCO ## "Colombia - Spanish" - esCR ## "Costa Rica - Spanish" - esDO ## "Dominican Republic - Spanish" - esEC ## "Ecuador - Spanish" - esES ## "Spain - Spanish" - esGT ## "Guatemala - Spanish" - esHN ## "Honduras - Spanish" - esMX ## "Mexico - Spanish" - esNI ## "Nicaragua - Spanish" - esPA ## "Panama - Spanish" - esPE ## "Peru - Spanish" - esPR ## "Puerto Rico - Spanish" - esPY ## "Paraguay - Spanish" - esSV ## "El Salvador - Spanish" - esUS ## "United States - Spanish" - esUY ## "Uruguay - Spanish" - esVE ## "Bolivarian Republic of Venezuela - Spanish" - etEE ## "Estonia - Estonian" - euES ## "Spain - Basque" - faIR ## "Iran - Persian" - fiFI ## "Finland - Finnish" - filPH ## "Philippines - Filipino" - foFO ## "Faroe Islands - Faroese" - frBE ## "Belgium - French" - frCA ## "Canada - French" - frCH ## "Switzerland - French" - frFR ## "France - French" - frLU ## "Luxembourg - French" - frMC ## "Principality of Monaco - French" - fyNL ## "Netherlands - Frisian" - gaIE ## "Ireland - Irish" - gdGB ## "United Kingdom - Scottish Gaelic" - glES ## "Spain - Galician" - gswFR ## "France - Alsatian" - guIN ## "India - Gujarati" - haNG ## "Nigeria - Hausa (Latin)" - heIL ## "Israel - Hebrew" - hiIN ## "India - Hindi" - hrBA ## "Bosnia and Herzegovina - Croatian" - hrHR ## "Croatia - Croatian" - hsbDE ## "Germany - Upper Sorbian" - huHU ## "Hungary - Hungarian" - hyAM ## "Armenia - Armenian" - idID ## "Indonesia - Indonesian" - igNG ## "Nigeria - Igbo" - iiCN ## "People's Republic of China - Yi" - isIS ## "Iceland - Icelandic" - itCH ## "Switzerland - Italian" - itIT ## "Italy - Italian" - iuCA ## "Canada - Inuktitut (Latin)" - jaJP ## "Japan - Japanese" - kaGE ## "Georgia - Georgian" - kkKZ ## "Kazakhstan - Kazakh" - klGL ## "Greenland - Greenlandic" - kmKH ## "Cambodia - Khmer" - knIN ## "India - Kannada" - koKR ## "Korea - Korean" - kokIN ## "India - Konkani" - kyKG ## "Kyrgyzstan - Kyrgyz" - lbLU ## "Luxembourg - Luxembourgish" - loLA ## "Lao P.D.R. - Lao" - ltLT ## "Lithuania - Lithuanian" - lvLV ## "Latvia - Latvian" - miNZ ## "New Zealand - Maori" - mkMK ## "Macedonia (FYROM) - Macedonian (FYROM)" - mlIN ## "India - Malayalam" - mnCN ## "People's Republic of China - Mongolian (Traditional Mongolian)" - mnMN ## "Mongolia - Mongolian (Cyrillic)" - mohCA ## "Canada - Mohawk" - mrIN ## "India - Marathi" - msBN ## "Brunei Darussalam - Malay" - msMY ## "Malaysia - Malay" - mtMT ## "Malta - Maltese" - nbNO ## "Norway - Norwegian (Bokmal)" - neNP ## "Nepal - Nepali" - nlBE ## "Belgium - Dutch" - nlNL ## "Netherlands - Dutch" - nnNO ## "Norway - Norwegian (Nynorsk)" - nsoZA ## "South Africa - Sesotho sa Leboa" - ocFR ## "France - Occitan" - orIN ## "India - Oriya" - paIN ## "India - Punjabi" - plPL ## "Poland - Polish" - prsAF ## "Afghanistan - Dari" - psAF ## "Afghanistan - Pashto" - ptBR ## "Brazil - Portuguese" - ptPT ## "Portugal - Portuguese" - qutGT ## "Guatemala - K'iche" - quzBO ## "Bolivia - Quechua" - quzEC ## "Ecuador - Quechua" - quzPE ## "Peru - Quechua" - rmCH ## "Switzerland - Romansh" - roRO ## "Romania - Romanian" - ruRU ## "Russia - Russian" - rwRW ## "Rwanda - Kinyarwanda" - saIN ## "India - Sanskrit" - sahRU ## "Russia - Yakut" - seFI ## "Finland - Sami (Northern)" - seNO ## "Norway - Sami (Northern)" - seSE ## "Sweden - Sami (Northern)" - siLK ## "Sri Lanka - Sinhala" - skSK ## "Slovakia - Slovak" - slSI ## "Slovenia - Slovenian" - smaNO ## "Norway - Sami (Southern)" - smaSE ## "Sweden - Sami (Southern)" - smjNO ## "Norway - Sami (Lule)" - smjSE ## "Sweden - Sami (Lule)" - smnFI ## "Finland - Sami (Inari)" - smsFI ## "Finland - Sami (Skolt)" - sqAL ## "Albania - Albanian" - srBA ## "Bosnia and Herzegovina - Serbian (Cyrillic)" - srCS ## "Serbia and Montenegro (Former) - Serbian (Cyrillic)" - srME ## "Montenegro - Serbian (Cyrillic)" - srRS ## "Serbia - Serbian (Cyrillic)" - svFI ## "Finland - Swedish" - svSE ## "Sweden - Swedish" - swKE ## "Kenya - Kiswahili" - syrSY ## "Syria - Syriac" - taIN ## "India - Tamil" - teIN ## "India - Telugu" - tgTJ ## "Tajikistan - Tajik (Cyrillic)" - thTH ## "Thailand - Thai" - tkTM ## "Turkmenistan - Turkmen" - tnZA ## "South Africa - Setswana" - trTR ## "Turkey - Turkish" - ttRU ## "Russia - Tatar" - tzmDZ ## "Algeria - Tamazight (Latin)" - ugCN ## "People's Republic of China - Uyghur" - ukUA ## "Ukraine - Ukrainian" - urPK ## "Islamic Republic of Pakistan - Urdu" - uzUZ ## "Uzbekistan - Uzbek (Cyrillic)" - viVN ## "Vietnam - Vietnamese" - woSN ## "Senegal - Wolof" - xhZA ## "South Africa - isiXhosa" - yoNG ## "Nigeria - Yoruba" - zhCN ## "People's Republic of China - Chinese (Simplified) Legacy" - zhHK ## "Hong Kong S.A.R. - Chinese (Traditional) Legacy" - zhMO ## "Macao S.A.R. - Chinese (Traditional) Legacy" - zhSG ## "Singapore - Chinese (Simplified) Legacy" - zhTW ## "Taiwan - Chinese (Traditional) Legacy" - zuZA ## "South Africa - isiZulu" - -const - languageToName*: array[Language, cstring] = [ - Language.afZA: cstring"South Africa - Afrikaans", - Language.amET: cstring"Ethiopia - Amharic", - Language.arAE: cstring"U.A.E. - Arabic", - Language.arBH: cstring"Bahrain - Arabic", - Language.arDZ: cstring"Algeria - Arabic", - Language.arEG: cstring"Egypt - Arabic", - Language.arIQ: cstring"Iraq - Arabic", - Language.arJO: cstring"Jordan - Arabic", - Language.arKW: cstring"Kuwait - Arabic", - Language.arLB: cstring"Lebanon - Arabic", - Language.arLY: cstring"Libya - Arabic", - Language.arMA: cstring"Morocco - Arabic", - Language.arOM: cstring"Oman - Arabic", - Language.arQA: cstring"Qatar - Arabic", - Language.arSA: cstring"Saudi Arabia - Arabic", - Language.arSY: cstring"Syria - Arabic", - Language.arTN: cstring"Tunisia - Arabic", - Language.arYE: cstring"Yemen - Arabic", - Language.arnCL: cstring"Chile - Mapudungun", - Language.asIN: cstring"India - Assamese", - Language.azAZ: cstring"Azerbaijan - Azeri (Cyrillic)", - Language.baRU: cstring"Russia - Bashkir", - Language.beBY: cstring"Belarus - Belarusian", - Language.bgBG: cstring"Bulgaria - Bulgarian", - Language.bnBD: cstring"Bangladesh - Bengali", - Language.bnIN: cstring"India - Bengali", - Language.boCN: cstring"People's Republic of China - Tibetan", - Language.brFR: cstring"France - Breton", - Language.bsBA: cstring"Bosnia and Herzegovina - Bosnian (Cyrillic)", - Language.caES: cstring"Spain - Catalan", - Language.coFR: cstring"France - Corsican", - Language.csCZ: cstring"Czech Republic - Czech", - Language.cyGB: cstring"United Kingdom - Welsh", - Language.daDK: cstring"Denmark - Danish", - Language.deAT: cstring"Austria - German", - Language.deCH: cstring"Switzerland - German", - Language.deDE: cstring"Germany - German", - Language.deLI: cstring"Liechtenstein - German", - Language.deLU: cstring"Luxembourg - German", - Language.dsbDE: cstring"Germany - Lower Sorbian", - Language.dvMV: cstring"Maldives - Divehi", - Language.elGR: cstring"Greece - Greek", - Language.en029: cstring"Caribbean - English", - Language.enAU: cstring"Australia - English", - Language.enBZ: cstring"Belize - English", - Language.enCA: cstring"Canada - English", - Language.enGB: cstring"United Kingdom - English", - Language.enIE: cstring"Ireland - English", - Language.enIN: cstring"India - English", - Language.enJM: cstring"Jamaica - English", - Language.enMY: cstring"Malaysia - English", - Language.enNZ: cstring"New Zealand - English", - Language.enPH: cstring"Republic of the Philippines - English", - Language.enSG: cstring"Singapore - English", - Language.enTT: cstring"Trinidad and Tobago - English", - Language.enUS: cstring"United States - English", - Language.enZA: cstring"South Africa - English", - Language.enZW: cstring"Zimbabwe - English", - Language.esAR: cstring"Argentina - Spanish", - Language.esBO: cstring"Bolivia - Spanish", - Language.esCL: cstring"Chile - Spanish", - Language.esCO: cstring"Colombia - Spanish", - Language.esCR: cstring"Costa Rica - Spanish", - Language.esDO: cstring"Dominican Republic - Spanish", - Language.esEC: cstring"Ecuador - Spanish", - Language.esES: cstring"Spain - Spanish", - Language.esGT: cstring"Guatemala - Spanish", - Language.esHN: cstring"Honduras - Spanish", - Language.esMX: cstring"Mexico - Spanish", - Language.esNI: cstring"Nicaragua - Spanish", - Language.esPA: cstring"Panama - Spanish", - Language.esPE: cstring"Peru - Spanish", - Language.esPR: cstring"Puerto Rico - Spanish", - Language.esPY: cstring"Paraguay - Spanish", - Language.esSV: cstring"El Salvador - Spanish", - Language.esUS: cstring"United States - Spanish", - Language.esUY: cstring"Uruguay - Spanish", - Language.esVE: cstring"Bolivarian Republic of Venezuela - Spanish", - Language.etEE: cstring"Estonia - Estonian", - Language.euES: cstring"Spain - Basque", - Language.faIR: cstring"Iran - Persian", - Language.fiFI: cstring"Finland - Finnish", - Language.filPH: cstring"Philippines - Filipino", - Language.foFO: cstring"Faroe Islands - Faroese", - Language.frBE: cstring"Belgium - French", - Language.frCA: cstring"Canada - French", - Language.frCH: cstring"Switzerland - French", - Language.frFR: cstring"France - French", - Language.frLU: cstring"Luxembourg - French", - Language.frMC: cstring"Principality of Monaco - French", - Language.fyNL: cstring"Netherlands - Frisian", - Language.gaIE: cstring"Ireland - Irish", - Language.gdGB: cstring"United Kingdom - Scottish Gaelic", - Language.glES: cstring"Spain - Galician", - Language.gswFR: cstring"France - Alsatian", - Language.guIN: cstring"India - Gujarati", - Language.haNG: cstring"Nigeria - Hausa (Latin)", - Language.heIL: cstring"Israel - Hebrew", - Language.hiIN: cstring"India - Hindi", - Language.hrBA: cstring"Bosnia and Herzegovina - Croatian", - Language.hrHR: cstring"Croatia - Croatian", - Language.hsbDE: cstring"Germany - Upper Sorbian", - Language.huHU: cstring"Hungary - Hungarian", - Language.hyAM: cstring"Armenia - Armenian", - Language.idID: cstring"Indonesia - Indonesian", - Language.igNG: cstring"Nigeria - Igbo", - Language.iiCN: cstring"People's Republic of China - Yi", - Language.isIS: cstring"Iceland - Icelandic", - Language.itCH: cstring"Switzerland - Italian", - Language.itIT: cstring"Italy - Italian", - Language.iuCA: cstring"Canada - Inuktitut (Latin)", - Language.jaJP: cstring"Japan - Japanese", - Language.kaGE: cstring"Georgia - Georgian", - Language.kkKZ: cstring"Kazakhstan - Kazakh", - Language.klGL: cstring"Greenland - Greenlandic", - Language.kmKH: cstring"Cambodia - Khmer", - Language.knIN: cstring"India - Kannada", - Language.koKR: cstring"Korea - Korean", - Language.kokIN: cstring"India - Konkani", - Language.kyKG: cstring"Kyrgyzstan - Kyrgyz", - Language.lbLU: cstring"Luxembourg - Luxembourgish", - Language.loLA: cstring"Lao P.D.R. - Lao", - Language.ltLT: cstring"Lithuania - Lithuanian", - Language.lvLV: cstring"Latvia - Latvian", - Language.miNZ: cstring"New Zealand - Maori", - Language.mkMK: cstring"Macedonia (FYROM) - Macedonian (FYROM)", - Language.mlIN: cstring"India - Malayalam", - Language.mnCN: cstring"People's Republic of China - Mongolian (Traditional Mongolian)", - Language.mnMN: cstring"Mongolia - Mongolian (Cyrillic)", - Language.mohCA: cstring"Canada - Mohawk", - Language.mrIN: cstring"India - Marathi", - Language.msBN: cstring"Brunei Darussalam - Malay", - Language.msMY: cstring"Malaysia - Malay", - Language.mtMT: cstring"Malta - Maltese", - Language.nbNO: cstring"Norway - Norwegian (Bokmal)", - Language.neNP: cstring"Nepal - Nepali", - Language.nlBE: cstring"Belgium - Dutch", - Language.nlNL: cstring"Netherlands - Dutch", - Language.nnNO: cstring"Norway - Norwegian (Nynorsk)", - Language.nsoZA: cstring"South Africa - Sesotho sa Leboa", - Language.ocFR: cstring"France - Occitan", - Language.orIN: cstring"India - Oriya", - Language.paIN: cstring"India - Punjabi", - Language.plPL: cstring"Poland - Polish", - Language.prsAF: cstring"Afghanistan - Dari", - Language.psAF: cstring"Afghanistan - Pashto", - Language.ptBR: cstring"Brazil - Portuguese", - Language.ptPT: cstring"Portugal - Portuguese", - Language.qutGT: cstring"Guatemala - K'iche", - Language.quzBO: cstring"Bolivia - Quechua", - Language.quzEC: cstring"Ecuador - Quechua", - Language.quzPE: cstring"Peru - Quechua", - Language.rmCH: cstring"Switzerland - Romansh", - Language.roRO: cstring"Romania - Romanian", - Language.ruRU: cstring"Russia - Russian", - Language.rwRW: cstring"Rwanda - Kinyarwanda", - Language.saIN: cstring"India - Sanskrit", - Language.sahRU: cstring"Russia - Yakut", - Language.seFI: cstring"Finland - Sami (Northern)", - Language.seNO: cstring"Norway - Sami (Northern)", - Language.seSE: cstring"Sweden - Sami (Northern)", - Language.siLK: cstring"Sri Lanka - Sinhala", - Language.skSK: cstring"Slovakia - Slovak", - Language.slSI: cstring"Slovenia - Slovenian", - Language.smaNO: cstring"Norway - Sami (Southern)", - Language.smaSE: cstring"Sweden - Sami (Southern)", - Language.smjNO: cstring"Norway - Sami (Lule)", - Language.smjSE: cstring"Sweden - Sami (Lule)", - Language.smnFI: cstring"Finland - Sami (Inari)", - Language.smsFI: cstring"Finland - Sami (Skolt)", - Language.sqAL: cstring"Albania - Albanian", - Language.srBA: cstring"Bosnia and Herzegovina - Serbian (Cyrillic)", - Language.srCS: cstring"Serbia and Montenegro (Former) - Serbian (Cyrillic)", - Language.srME: cstring"Montenegro - Serbian (Cyrillic)", - Language.srRS: cstring"Serbia - Serbian (Cyrillic)", - Language.svFI: cstring"Finland - Swedish", - Language.svSE: cstring"Sweden - Swedish", - Language.swKE: cstring"Kenya - Kiswahili", - Language.syrSY: cstring"Syria - Syriac", - Language.taIN: cstring"India - Tamil", - Language.teIN: cstring"India - Telugu", - Language.tgTJ: cstring"Tajikistan - Tajik (Cyrillic)", - Language.thTH: cstring"Thailand - Thai", - Language.tkTM: cstring"Turkmenistan - Turkmen", - Language.tnZA: cstring"South Africa - Setswana", - Language.trTR: cstring"Turkey - Turkish", - Language.ttRU: cstring"Russia - Tatar", - Language.tzmDZ: cstring"Algeria - Tamazight (Latin)", - Language.ugCN: cstring"People's Republic of China - Uyghur", - Language.ukUA: cstring"Ukraine - Ukrainian", - Language.urPK: cstring"Islamic Republic of Pakistan - Urdu", - Language.uzUZ: cstring"Uzbekistan - Uzbek (Cyrillic)", - Language.viVN: cstring"Vietnam - Vietnamese", - Language.woSN: cstring"Senegal - Wolof", - Language.xhZA: cstring"South Africa - isiXhosa", - Language.yoNG: cstring"Nigeria - Yoruba", - Language.zhCN: cstring"People's Republic of China - Chinese (Simplified) Legacy", - Language.zhHK: cstring"Hong Kong S.A.R. - Chinese (Traditional) Legacy", - Language.zhMO: cstring"Macao S.A.R. - Chinese (Traditional) Legacy", - Language.zhSG: cstring"Singapore - Chinese (Simplified) Legacy", - Language.zhTW: cstring"Taiwan - Chinese (Traditional) Legacy", - Language.zuZA: cstring"South Africa - isiZulu"] - - languageToCode*: array[Language, cstring] = [ - Language.afZA: cstring"af-ZA", - Language.amET: cstring"am-ET", - Language.arAE: cstring"ar-AE", - Language.arBH: cstring"ar-BH", - Language.arDZ: cstring"ar-DZ", - Language.arEG: cstring"ar-EG", - Language.arIQ: cstring"ar-IQ", - Language.arJO: cstring"ar-JO", - Language.arKW: cstring"ar-KW", - Language.arLB: cstring"ar-LB", - Language.arLY: cstring"ar-LY", - Language.arMA: cstring"ar-MA", - Language.arOM: cstring"ar-OM", - Language.arQA: cstring"ar-QA", - Language.arSA: cstring"ar-SA", - Language.arSY: cstring"ar-SY", - Language.arTN: cstring"ar-TN", - Language.arYE: cstring"ar-YE", - Language.arnCL: cstring"arn-CL", - Language.asIN: cstring"as-IN", - Language.azAZ: cstring"az-AZ", - Language.baRU: cstring"ba-RU", - Language.beBY: cstring"be-BY", - Language.bgBG: cstring"bg-BG", - Language.bnBD: cstring"bn-BD", - Language.bnIN: cstring"bn-IN", - Language.boCN: cstring"bo-CN", - Language.brFR: cstring"br-FR", - Language.bsBA: cstring"bs-BA", - Language.caES: cstring"ca-ES", - Language.coFR: cstring"co-FR", - Language.csCZ: cstring"cs-CZ", - Language.cyGB: cstring"cy-GB", - Language.daDK: cstring"da-DK", - Language.deAT: cstring"de-AT", - Language.deCH: cstring"de-CH", - Language.deDE: cstring"de-DE", - Language.deLI: cstring"de-LI", - Language.deLU: cstring"de-LU", - Language.dsbDE: cstring"dsb-DE", - Language.dvMV: cstring"dv-MV", - Language.elGR: cstring"el-GR", - Language.en029: cstring"en-029", - Language.enAU: cstring"en-AU", - Language.enBZ: cstring"en-BZ", - Language.enCA: cstring"en-CA", - Language.enGB: cstring"en-GB", - Language.enIE: cstring"en-IE", - Language.enIN: cstring"en-IN", - Language.enJM: cstring"en-JM", - Language.enMY: cstring"en-MY", - Language.enNZ: cstring"en-NZ", - Language.enPH: cstring"en-PH", - Language.enSG: cstring"en-SG", - Language.enTT: cstring"en-TT", - Language.enUS: cstring"en-US", - Language.enZA: cstring"en-ZA", - Language.enZW: cstring"en-ZW", - Language.esAR: cstring"es-AR", - Language.esBO: cstring"es-BO", - Language.esCL: cstring"es-CL", - Language.esCO: cstring"es-CO", - Language.esCR: cstring"es-CR", - Language.esDO: cstring"es-DO", - Language.esEC: cstring"es-EC", - Language.esES: cstring"es-ES", - Language.esGT: cstring"es-GT", - Language.esHN: cstring"es-HN", - Language.esMX: cstring"es-MX", - Language.esNI: cstring"es-NI", - Language.esPA: cstring"es-PA", - Language.esPE: cstring"es-PE", - Language.esPR: cstring"es-PR", - Language.esPY: cstring"es-PY", - Language.esSV: cstring"es-SV", - Language.esUS: cstring"es-US", - Language.esUY: cstring"es-UY", - Language.esVE: cstring"es-VE", - Language.etEE: cstring"et-EE", - Language.euES: cstring"eu-ES", - Language.faIR: cstring"fa-IR", - Language.fiFI: cstring"fi-FI", - Language.filPH: cstring"fil-PH", - Language.foFO: cstring"fo-FO", - Language.frBE: cstring"fr-BE", - Language.frCA: cstring"fr-CA", - Language.frCH: cstring"fr-CH", - Language.frFR: cstring"fr-FR", - Language.frLU: cstring"fr-LU", - Language.frMC: cstring"fr-MC", - Language.fyNL: cstring"fy-NL", - Language.gaIE: cstring"ga-IE", - Language.gdGB: cstring"gd-GB", - Language.glES: cstring"gl-ES", - Language.gswFR: cstring"gsw-FR", - Language.guIN: cstring"gu-IN", - Language.haNG: cstring"ha-NG", - Language.heIL: cstring"he-IL", - Language.hiIN: cstring"hi-IN", - Language.hrBA: cstring"hr-BA", - Language.hrHR: cstring"hr-HR", - Language.hsbDE: cstring"hsb-DE", - Language.huHU: cstring"hu-HU", - Language.hyAM: cstring"hy-AM", - Language.idID: cstring"id-ID", - Language.igNG: cstring"ig-NG", - Language.iiCN: cstring"ii-CN", - Language.isIS: cstring"is-IS", - Language.itCH: cstring"it-CH", - Language.itIT: cstring"it-IT", - Language.iuCA: cstring"iu-CA", - Language.jaJP: cstring"ja-JP", - Language.kaGE: cstring"ka-GE", - Language.kkKZ: cstring"kk-KZ", - Language.klGL: cstring"kl-GL", - Language.kmKH: cstring"km-KH", - Language.knIN: cstring"kn-IN", - Language.koKR: cstring"ko-KR", - Language.kokIN: cstring"kok-IN", - Language.kyKG: cstring"ky-KG", - Language.lbLU: cstring"lb-LU", - Language.loLA: cstring"lo-LA", - Language.ltLT: cstring"lt-LT", - Language.lvLV: cstring"lv-LV", - Language.miNZ: cstring"mi-NZ", - Language.mkMK: cstring"mk-MK", - Language.mlIN: cstring"ml-IN", - Language.mnCN: cstring"mn-CN", - Language.mnMN: cstring"mn-MN", - Language.mohCA: cstring"moh-CA", - Language.mrIN: cstring"mr-IN", - Language.msBN: cstring"ms-BN", - Language.msMY: cstring"ms-MY", - Language.mtMT: cstring"mt-MT", - Language.nbNO: cstring"nb-NO", - Language.neNP: cstring"ne-NP", - Language.nlBE: cstring"nl-BE", - Language.nlNL: cstring"nl-NL", - Language.nnNO: cstring"nn-NO", - Language.nsoZA: cstring"nso-ZA", - Language.ocFR: cstring"oc-FR", - Language.orIN: cstring"or-IN", - Language.paIN: cstring"pa-IN", - Language.plPL: cstring"pl-PL", - Language.prsAF: cstring"prs-AF", - Language.psAF: cstring"ps-AF", - Language.ptBR: cstring"pt-BR", - Language.ptPT: cstring"pt-PT", - Language.qutGT: cstring"qut-GT", - Language.quzBO: cstring"quz-BO", - Language.quzEC: cstring"quz-EC", - Language.quzPE: cstring"quz-PE", - Language.rmCH: cstring"rm-CH", - Language.roRO: cstring"ro-RO", - Language.ruRU: cstring"ru-RU", - Language.rwRW: cstring"rw-RW", - Language.saIN: cstring"sa-IN", - Language.sahRU: cstring"sah-RU", - Language.seFI: cstring"se-FI", - Language.seNO: cstring"se-NO", - Language.seSE: cstring"se-SE", - Language.siLK: cstring"si-LK", - Language.skSK: cstring"sk-SK", - Language.slSI: cstring"sl-SI", - Language.smaNO: cstring"sma-NO", - Language.smaSE: cstring"sma-SE", - Language.smjNO: cstring"smj-NO", - Language.smjSE: cstring"smj-SE", - Language.smnFI: cstring"smn-FI", - Language.smsFI: cstring"sms-FI", - Language.sqAL: cstring"sq-AL", - Language.srBA: cstring"sr-BA", - Language.srCS: cstring"sr-CS", - Language.srME: cstring"sr-ME", - Language.srRS: cstring"sr-RS", - Language.svFI: cstring"sv-FI", - Language.svSE: cstring"sv-SE", - Language.swKE: cstring"sw-KE", - Language.syrSY: cstring"syr-SY", - Language.taIN: cstring"ta-IN", - Language.teIN: cstring"te-IN", - Language.tgTJ: cstring"tg-TJ", - Language.thTH: cstring"th-TH", - Language.tkTM: cstring"tk-TM", - Language.tnZA: cstring"tn-ZA", - Language.trTR: cstring"tr-TR", - Language.ttRU: cstring"tt-RU", - Language.tzmDZ: cstring"tzm-DZ", - Language.ugCN: cstring"ug-CN", - Language.ukUA: cstring"uk-UA", - Language.urPK: cstring"ur-PK", - Language.uzUZ: cstring"uz-UZ", - Language.viVN: cstring"vi-VN", - Language.woSN: cstring"wo-SN", - Language.xhZA: cstring"xh-ZA", - Language.yoNG: cstring"yo-NG", - Language.zhCN: cstring"zh-CN", - Language.zhHK: cstring"zh-HK", - Language.zhMO: cstring"zh-MO", - Language.zhSG: cstring"zh-SG", - Language.zhTW: cstring"zh-TW", - Language.zuZA: cstring"zu-ZA"] diff --git a/karax/lookuptables.nim b/karax/lookuptables.nim deleted file mode 100644 index 1a1d51d..0000000 --- a/karax/lookuptables.nim +++ /dev/null @@ -1,38 +0,0 @@ - -import macros, kbase -from strutils import `%` - -macro fieldNamesAsArray*(t: typed; pattern = "$1"): untyped = - var impl = getTypeImpl(getTypeImpl(t)[1]) - if impl.kind == nnkRefTy: impl = getTypeImpl(impl[0]) - expectKind impl, nnkObjectTy - impl = impl[2] - expectKind impl, nnkRecList - result = newTree(nnkBracket) - for x in impl: - expectKind x, nnkIdentDefs - result.add(newCall(bindSym"kstring", newLit(pattern.strVal % $x[0]))) - -proc str(n: NimNode): NimNode = - if n.kind in {nnkStrLit, nnkTripleStrLit}: - result = newCall(bindSym"kstring", n) - else: - result = copyNimNode(n) - for i in 0..= 0: - x.s.delete(position) - x.broadcast(Mark) - x.broadcast(Deleted, position) - -when false: - proc `:=`[T](x: Reactive[T], f: proc(): T) = - toTrack = wrapObserver(f()) - x.value = f() - toTrack = nil - - proc map*[T, U](x: RSeq[T], f: proc(x: T): U): RSeq[U] = - let xl = x.L.value - let res = newRSeq[U](xl) - for i in 0..