Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
# Conflicts:
#	Project.toml
  • Loading branch information
essenciary committed Mar 6, 2024
2 parents 12a15dc + 8bb0a1c commit 3e0e409
Show file tree
Hide file tree
Showing 11 changed files with 125 additions and 47 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
version:
- '1.6'
- '1.7'
- 'nightly'
- '1.10'
os:
- ubuntu-latest
- macOS-latest
Expand Down
24 changes: 13 additions & 11 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,28 @@ Observables = "510215fc-4207-5dde-b226-833fc4488ee2"
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
Parameters = "d96e819e-fc66-5662-9728-84c9c7592b0a"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
StructTypes = "856f2bd8-1eba-4b0a-8007-ebc267875bd4"
Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"

[weakdeps]
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"

[extensions]
StippleDataFramesExt = "DataFrames"
StippleJSONExt = "JSON"
StippleOffsetArraysExt = "OffsetArrays"

[compat]
DataFrames = "1"
Dates = "1.6"
FilePathsBase = "0.9"
Genie = "5.23.8"
Genie = "5.24.4"
GenieSession = "1"
GenieSessionFileSession = "1"
JSON = "0.20, 0.21"
Expand All @@ -40,18 +51,14 @@ OffsetArrays = "1"
OrderedCollections = "1"
Parameters = "0.12"
Pkg = "1.6"
PrecompileTools = "1.2"
Random = "1.6"
Reexport = "1"
Requires = "1"
StructTypes = "1.8"
Tables = "1"
julia = "1.6"

[extensions]
StippleDataFramesExt = "DataFrames"
StippleJSONExt = "JSON"
StippleOffsetArraysExt = "OffsetArrays"

[extras]
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
Expand All @@ -60,8 +67,3 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test", "DataFrames", "JSON", "OffsetArrays"]

[weakdeps]
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
17 changes: 16 additions & 1 deletion assets/css/stipplecore.css
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@
border-radius: 5px;
box-shadow: 0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);
}
.stipple-core header {
padding-top:5px;
padding-left: 5px;
}

.stipple-core a {
color: steelblue;
}

.container { margin-bottom: 20px; }
.stipple-core .st-module > h1,
.stipple-core .st-module > h2,
Expand Down Expand Up @@ -87,7 +96,9 @@
.stipple-core .text-h1,
.stipple-core h1 {
line-height: 2.5rem;
font-size: 4rem;
}

.stipple-core .text-h2,
.stipple-core h2 {
line-height: 2rem;
Expand Down Expand Up @@ -265,6 +276,10 @@
.stipple-core .q-field--standout .text-white .q-field__native {
color: var(--q-color-white);
}
.stipple-core .q-field__control-container .material-icons {
margin-top: auto;
margin-bottom: auto;
}
.stipple-core .q-badge {
font-weight: 700;
padding: 4px 6px;
Expand Down Expand Up @@ -540,4 +555,4 @@ body > .q-loading-bar {
}
}

[v-cloak] { display: none; }
[v-cloak] { display: none; }
1 change: 1 addition & 0 deletions ext/StippleJSONExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ Stipple.JSONText(json::JSON.JSONText) = Stipple.JSONText(json.s)
@inline StructTypes.construct(::Type{JSON.JSONText}, json::JSON3.RawValue) = JSON.JSONText(string(json))
@inline JSON3.rawbytes(json::JSON.JSONText) = codeunits(json.s)

Stipple.js_print(io::IO, js::JSON.JSONText) = print(io, js.s)
end
4 changes: 2 additions & 2 deletions src/Elements.jl
Original file line number Diff line number Diff line change
Expand Up @@ -443,8 +443,8 @@ julia> stylesheet("https://fonts.googleapis.com/css?family=Material+Icons")
"<link href=\"https://fonts.googleapis.com/css?family=Material+Icons\" rel=\"stylesheet\" />"
```
"""
function stylesheet(href::String; args...) :: ParsedHTMLString
Genie.Renderer.Html.link(href=href, rel="stylesheet", args...)
function stylesheet(href::String; kwargs...) :: ParsedHTMLString
Genie.Renderer.Html.link(href=href, rel="stylesheet"; kwargs...)
end

end
4 changes: 2 additions & 2 deletions src/ReactiveTools.jl
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ end

macro add_vars(expr)
init_storage(__module__)
REACTIVE_STORAGE[__module__] = Stipple.merge_storage(REACTIVE_STORAGE[__module__], @eval(__module__, Stipple.@var_storage($expr)))
REACTIVE_STORAGE[__module__] = Stipple.merge_storage(REACTIVE_STORAGE[__module__], @eval(__module__, Stipple.@var_storage($expr)); context = __module__)

update_storage(__module__)
end
Expand Down Expand Up @@ -670,7 +670,7 @@ macro mixin(location, expr, prefix, postfix)
M = $x isa DataType ? $x : typeof($x) # really needed?
local mixin_storage = Stipple.model_to_storage(M, $(QuoteNode(prefix)), $postfix)

merge!(storage, Stipple.merge_storage(storage, mixin_storage))
merge!(storage, Stipple.merge_storage(storage, mixin_storage; context = @__MODULE__))
location isa DataType || location isa Symbol ? eval(:(Stipple.@type($$loc, $storage))) : location
mixin_storage
end |> esc
Expand Down
76 changes: 58 additions & 18 deletions src/Stipple.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ existing Vue.js libraries.
"""
module Stipple

using PrecompileTools
const PRECOMPILE = Ref(false)
const ALWAYS_REGISTER_CHANNELS = Ref(true)
const USE_MODEL_STORAGE = Ref(true)
Expand Down Expand Up @@ -619,27 +620,25 @@ function init(t::Type{M};
end

ch = "/$channel/events"
if ! Genie.Router.ischannel(Router.channelname(ch))
Genie.Router.channel(ch, named = Router.channelname(ch)) do
# get event name
event = Genie.Requests.payload(:payload)["event"]
# form handler parameter & call event notifier
handler = Symbol(get(event, "name", nothing))
event_info = get(event, "event", nothing)

# add client id if requested
if event_info isa Dict && get(event_info, "_addclient", false)
client = transport == Genie.WebChannels ? Genie.WebChannels.id(Genie.Requests.wsclient()) : Genie.Requests.wtclient()
push!(event_info, "_client" => client)
end
Genie.Router.channel(ch, named = Router.channelname(ch)) do
# get event name
event = Genie.Requests.payload(:payload)["event"]
# form handler parameter & call event notifier
handler = Symbol(get(event, "name", nothing))
event_info = get(event, "event", nothing)

# add client id if requested
if event_info isa Dict && get(event_info, "_addclient", false)
client = transport == Genie.WebChannels ? Genie.WebChannels.id(Genie.Requests.wsclient()) : Genie.Requests.wtclient()
push!(event_info, "_client" => client)
end

isempty(methods(notify, (M, Val{handler}))) || notify(model, Val(handler))
isempty(methods(notify, (M, Val{handler}, Any))) || notify(model, Val(handler), event_info)
isempty(methods(notify, (M, Val{handler}))) || notify(model, Val(handler))
isempty(methods(notify, (M, Val{handler}, Any))) || notify(model, Val(handler), event_info)

LAST_ACTIVITY[Symbol(channel)] = now()
LAST_ACTIVITY[Symbol(channel)] = now()

ok_response
end
ok_response
end
end

Expand Down Expand Up @@ -1287,4 +1286,45 @@ include("Layout.jl")
@reexport using .Elements
@reexport using .Layout

# precompilation ...

using Stipple.ReactiveTools
@setup_workload begin
# Putting some things in `setup` can reduce the size of the
# precompile file and potentially make loading faster.
using Genie.HTTPUtils.HTTP
PRECOMPILE[] = true
@compile_workload begin
# all calls in this block will be precompiled, regardless of whether
# they belong to your package or not (on Julia 1.8 and higher)
ui() = [cell("hello"), row("world"), htmldiv("Hello World")]

@app PrecompileApp begin
@in demo_i = 1
@out demo_s = "Hi"

@onchange demo_i begin
println(demo_i)
end
end

route("/") do
model = Stipple.ReactiveTools.@init PrecompileApp
page(model, ui) |> html
end
port = tryparse(Int, get(ENV, "STIPPLE_PRECOMPILE_PORT", ""))
port === nothing && (port = rand(8081:8999))
up(port)

precompile_get = tryparse(Bool, get(ENV, "STIPPLE_PRECOMPILE_GET", "1"))
precompile_get === true && HTTP.get("http://localhost:$port")
# The following lines (still) produce an error although
# they pass at the repl. Not very important though.
# HTTP.get("http://localhost:$port$(Genie.Assets.asset_path(Genie.assets_config, :js, file = "channels"))")
# HTTP.get("http://localhost:$port$(Genie.Assets.asset_path(assets_config, :js, file = "stipplecore"))")
down()
end
PRECOMPILE[] = false
end

end
12 changes: 6 additions & 6 deletions src/stipple/jsintegration.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ Checks whether the string is a valid js function and returns a `Dict` from which
in the backend can construct a function.
"""
function parse_jsfunction(s::AbstractString)
# look for classical function definition
m = match( r"function\s*\(([^)]*)\)\s*{(.*)}"s, s)
# look for classical function definition (not a full syntax check, though)
m = match( r"^\s*function\s*\(([^)]*)\)\s*{(.*)}\s*$"s, s)
!isnothing(m) && length(m.captures) == 2 && return opts(arguments=m[1], body=m[2])

# look for pure function definition
m = match( r"\s*\(?([^=)]*?)\)?\s*=>\s*({*.*?}*)\s*$"s , s )
# look for pure function definition including unbracketed single parameter
m = match( r"^\s*\(?([^=<>:;.(){}\[\]]*?)\)?\s*=>\s*({*.*?}*)\s*$"s , s )
(isnothing(m) || length(m.captures) != 2) && return nothing

# if pure function body is without curly brackets, add a `return`, otherwise strip the brackets
# Note: for utf-8 strings m[2][2:end-1] will fail if the string ends with a wide character, e.g. ϕ
body = startswith(m[2], "{") ? m[2][2:prevind(m[2], lastindex(m[2]))] : "return " * m[2]
Expand Down
10 changes: 10 additions & 0 deletions src/stipple/parsers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,14 @@ end
#String to AbstractFloat
function stipple_parse(::Type{T}, value::String) where T<:AbstractFloat
Base.parse(T, value)
end

# Union with Nothing
function stipple_parse(::Type{Union{Nothing, T}}, ::Nothing) where T
nothing
end

# Union with Nothing
function stipple_parse(::Type{Union{Nothing, T}}, value) where T
stipple_parse(T, value)
end
10 changes: 5 additions & 5 deletions src/stipple/reactivity.jl
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,9 @@ function model_to_storage(::Type{T}, prefix = "", postfix = "") where T# <: Reac
storage
end

function merge_storage(storage_1::AbstractDict, storage_2::AbstractDict; keep_channel = true)
m1 = eval(haskey(storage_1, :modes__) ? storage_1[:modes__].args[end] : LittleDict{Symbol, Int}())
m2 = eval(haskey(storage_2, :modes__) ? storage_2[:modes__].args[end] : LittleDict{Symbol, Int}())
function merge_storage(storage_1::AbstractDict, storage_2::AbstractDict; keep_channel = true, context::Module)
m1 = haskey(storage_1, :modes__) ? Core.eval(context, storage_1[:modes__].args[end]) : LittleDict{Symbol, Int}()
m2 = haskey(storage_2, :modes__) ? Core.eval(context, storage_2[:modes__].args[end]) : LittleDict{Symbol, Int}()
modes = merge(m1, m2)

keep_channel && haskey(storage_2, :channel__) && (storage_2 = delete!(copy(storage_2), :channel__))
Expand Down Expand Up @@ -375,7 +375,7 @@ macro var_storage(expr, new_inputmode = :auto)
end

mixin_storage = @eval __module__ Stipple.model_to_storage($(e.args[2]), $prefix, $postfix)
storage = merge_storage(storage, mixin_storage)
storage = merge_storage(storage, mixin_storage; context = __module__)
end
:modes__, e
end
Expand Down Expand Up @@ -482,7 +482,7 @@ macro add_vars(modelname, expr, new_inputmode = :auto)
storage = @eval(__module__, Stipple.@var_storage($expr, $new_inputmode))
new_storage = if isdefined(__module__, modelname)
old_storage = @eval(__module__, Stipple.model_to_storage($modelname))
ReactiveTools.merge_storage(old_storage, storage)
ReactiveTools.merge_storage(old_storage, storage; context = __module__)
else
storage
end
Expand Down
12 changes: 11 additions & 1 deletion src/stipple/rendering.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
"""
js_print(io::IO, x)
Stipple internal print routine for join_js.
Mainly used to allow for printing of JSON.JSONText
"""
js_print(io::IO, x) = print(io, x)

"""
join_js(xx, delim = ""; skip_empty = true, pre::Function = identity,
strip_delimiter = true, pre_delim::Union{Function,Nothing} = nothing)
Expand Down Expand Up @@ -42,8 +50,10 @@ function join_js(xx, delim = ""; skip_empty = true, pre::Function = identity, st
if x isa Union{AbstractDict, Pair, Base.Iterators.Pairs, Vector{<:Pair}}
s = json(Dict(k => JSONText(v) for (k, v) in (x isa Pair ? [x] : x)))[2:end - 1]
print(io2, s)
elseif x isa JSONText
print(io2, x.s)
else
print(io2, x)
js_print(io2, x)
end
s = String(take!(io2))
hasdelimiter = strip_delimiter && endswith(s, delim)
Expand Down

2 comments on commit 3e0e409

@essenciary
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/102365

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.28.5 -m "<description of version>" 3e0e4097beb7e85e3f8f24f2912e24bd9371d415
git push origin v0.28.5

Please sign in to comment.