Open reuleaux opened 7 months ago
I do remember I was bitten by this quirk before. I think I used workaround with my own renderer just as you did, but since we've got another victim, I think it's time to address this once and for all.
Providing yet another sxml->html is not very difficult, but I don't like having multiple similar libraries in bundle. I've refrained from modifying sxml libraries from the original, so that it would be easier to follow the upstream update, but sxml development seems stalled for years so I may just go and fix it in the library.
And I am adding: given that the above function sxml->html-string uses double quotes for attributes, like so:
<input type="text" class="v" readonly="t" name="lastName" id="lastName" value="Antonio" />
I am challenging this approach: misusing my input-type-text mobile field again - writing not only a mobile telephone number, but some double quotes, as well, say:
mobile:
0987654321 the "Lioness"
and the server responds this time correctly (using the above sxml->html-string function) with:
<input type="text" readonly="t" name="mobile" id="mobile" value="0987654321 - "the Lioness"" />
without me having to think about any escaping.
Ah, and I have only now read your message above: yes fine: do what you consider is appropriate (and let me know) - and I will use my own renderer for now, and then the updated libraries (once you have fixed them)
Ah, and one more remark and one more question:
You might as well look at the Guile way of handling all thing web: below is a simple web server in Guile: this is all very low level stuff (nowhere near the comfort of Makiki): you have to write your own dispatcher, etc. - but (!) their sxml->xml function (from (sxml simple)) returns xml correctly quoted in double quotes (I think they have also a sxml->html function, I don't remember why I have used the sxml->xml function instead - or maybe I am wrong: there is no such sxml->html function, and therefore the article by David Thompson). - You will find more explanations in the Guile Reference Manual.
...Which brings me to another question - with regards to Makiki: I have always wondered why the respond/* functions need the req as argument in Makiki
(respond/ok req someanswer)
I am sure there is a technical reason, but (on this low level of Guile at least - as below - that is not necessary:
(respond someanswer)
Which seems simpler to me, and also more in harmony with the intuition of communication:
You ask me question, like: "How are you?" (req)
And I respond: "Thanks, fine!" (respond , respond/ok) (i.e. I just respond, I don't usually repeat your question: "How are you? - Thanks, fine!" or: "How am I? - Thanks, fine!"
(You do this kind of always repeating the question with the elderly who have hearing issues, but not in normal day to day conversation.)
I would be curious to know why in Makiki the req is required in all the
response functions. (apparently on a lower level: as in Guile below this
is not necessary (one can just call: (respond (page))
below).
Thanks again, Andreas
file basic.scm
#!/usr/bin/guile \
-e main -s
!#
(read-set! keywords 'prefix)
(use-modules
(web server)
(web request)
(web response)
(web uri)
(sxml simple)
;; (sxml xpath)
)
(define (page)
`(html (@ (lang en))
(head
(meta (@ (charset utf-8)))
(title page)
(link (@
(type text/css)
(rel stylesheet)
(href /main.css)
))
(body
(div (@ (id main))
(span "blah")
)
))
))
(define* (respond
:optional body
:key
(status 200)
(doctype "<!DOCTYPE html>\n")
(content-type-params '((charset . "utf-8")))
(content-type 'text/html)
(extra-headers '())
(sxml body)
)
(values (build-response
:code status
:headers `((content-type
. (,content-type ,@content-type-params))
,@extra-headers)
:port 8080
)
(lambda (port)
(if sxml
(begin
(if doctype (display doctype port))
(sxml->xml sxml port))))))
(define (dispatch request body)
(let
(
[path (uri-path (request-uri request))]
;; [query (uri-query (request-uri request))]
)
(cond
[(string= path "/page")
(respond (page))
]
[else
(respond "not found")
]
)
))
(define (main args)
(run-server dispatch)
)
The request packet is not merely a static data to represent a request, but rather managing the context of that reqest-response. Some info in it is used to produce the response. (So it may be a misnomer, but 'context' is too generic.)
The reason that we carry around a request (or context) packet is to allow "wrapper" pattern in a consistent way. Remember, a handler is a procedure (lambda (request app-data) ...)
. You can provide a library to add a specific feature with (lambda (inner-handler) (lambda (request app-data) ...do-something-with-request-packet... (inner-handler request app-data)))
. See with-*
procedures in makiki.scm
.
By having a single packet to carry the context, all with-*
procedures can be easily composed together.
OK, Great! - And thanks for this explanation!
Pushed a fix to Gauche repo for attribute value escaping in sxml:sxml->xml
and sxml:sxml->html
. Can you try it to see it addresses your original issue?
Hm, I am not sure - but this might as well be my bad: I did install Gauche with
get-gauche.sh --auto --prefix ~/opt/gauche
Now, when I do:
get-gauche.sh --auto --prefix ~/opt/gauche
You already have Gauche 0.9.14 in '/home/rx/opt/gauche/bin/gosh'.
No need to install. (Use --force option to install 0.9.14.)
therefore I do
get-gauche.sh --auto --prefix ~/opt/gauche --force
which then did recompile/reinstall gauche - I am not sure though: maybe this is just for Gauche releases? And this is not the proper way to update to git head as well? - as one would normally do with git fetch & git merge origin/master e.g.? Anyway, with this reinstalled Gauche (as I said: this may not be completely up to date ) I still have the issue when now using
(respond/ok req (edit))
and my edit form being defined as
(define (edit)
`(sxml
(html (@ (lang "en"))
....
))
I am busy in the next hours - but I will get back to this - and move to a more manual git work flow with gauche, I guess: git fetch & git merge - so I know at least what version / patches I am working with (or maybe just brutally remove all of my gauche, and use try get-gauche again:
so basically - with this probably not quite up-to-date gauche I am currently stlill seeing (then in my view form):
<input type='text' readonly='t' name='mobile' id='mobile' value='0987654321 - Nov '23'>
so there are two things here:
If one uses single quotes for attributes (as is the case above): then obviously single quotes must be escaped.
If double quotes are used (which I would find nicer style - by the way) like so
<input type="text" readonly="t" name="mobile" id="mobile" value="0987654321 - Nov '23">
then this November '23 example is not an issue, but one has to properly escape double quotes: for values like: 09876543 - the "Lioness"
Did you stick with single quotes for attributes? and are now escaping them for values? Or did you choose double quotes? - I haven't had the time yet to look at your patch in detail. - Anyway: I will get back to this later. thanks so far.
OK (as I understand:) I need to set up a proper dev environment, git clone gauche, and follow the steps in the HACKING document.
And I seem to remember: I need a proper release installed first (which I have: with get-gauche as above), for I can build this dev gauche - it needs gosh during the build process.
Thus with my release gauche in ~/opt/gauche. I trying to build a devgauche now:
git clone https://github.com/shirok/Gauche devgauche
cd devgauche
./DIST gen
./configure --prefix ~/opt/devgauche
some complaints about tls: I will look into this later (--with-tls), and then
make
having my release gosh in my path, or as a function in my case: like so
$ type gosh
gosh is a function
gosh ()
{
~/opt/gauche/bin/gosh -I. "$@"
}
rx@softland ~ $
maybe just having ~/opt/gauche/bin in my path would be better? - Anyway: make stops at some point with
...
GAUCHE_LOAD_PATH="" GAUCHE_DYNLOAD_PATH="" "/home/rx/opt/gauche/bin/gosh" -v:0.9.14 -l./preload -I../src -I../lib -I../lib -I. `cat ./features.flags` ../lib/tools/precomp -D LIBGAUCHE_BODY libextra.scm
gosh: "ERROR": cannot find "gauche/collection" in ("/home/rx/opt/devgauche/share/gauche-0.98/site/lib" "/home/rx/opt/devgauche/share/gauche-0.98/0.9.14/lib")
make[1]: *** [Makefile:29: libextra.c] Error 1
make[1]: Leaving directory '/home/rx/tmp/gauche/src'
make: *** [Makefile:47: all] Error 1
rx@softland {master} ~/tmp/gauche $
Maybe I have to set some more variables (pointing to my release gauche in ~/opt/gauche for things like gauche/collection to be found?
maybe I need this % gauche-config --reconfigure | sh
step (as on the download page)?
Anyway, I am continuing with this...
Thanks so far.
Best bet is to include your installation path in PATH
. I test it in that way all the time.
Sometimes, if your previous build is incomplete, some unsatisfied dependency causes a build error; generally starting over from make distclean
solves the issue.
I am one step further: got a development Gauche installed, and can confirm that with this latest (git head) Gauche, the escaping of attributes in (nice now:) double quotes works fine! Many thanks.
My way of installing was this: as explained above I had previously installed Gauche with
./get-gauche.sh --auto --prefix ~/opt/gauche
I call this a release gauche (Gauche 0.9.14 in ~/opt/gauche), and I didn't want to touch this / mess with this, as already I am relying on some working gauche on my system.
Now, while previously/above having tried to install a development version of Gauche in ~/opt/devgauche, by making use of this already installed release gauche - I guess this all got too confusing at some point with regards to the paths: two different gauche paths: ~/opt/gauche/bin and ~/opt/devgauche/bin ... (but maybe it is possible somehow w/ BUILD_GOSH - I haven't tried this any further), I have now installed:
(1) first a release gauche in ~/opt/devgauche with
./get-gauche.sh --auto --prefix ~/opt/devgauche
(2) and then into this same location a dev gauche with
./configure --prefix ~/opt/devgauche --with-tls=none
make
make check
make install
having my path set with
export PATH=$PATH:$HOME/opt/devgauche/bin
i.e. both: the release gauche, and the yet to built gauche (during installation) sharing the same (bin and make target) path. This worked fine! - And now with makiki installed again, html rendering works fine:
(in the view form sent back by the server, having made some challenging changes in the edit form):
rendering attributes with single quotes isn't an issue (needs no escaping), as attributes are rendered in double quotes now (nice, thanks!):
<input type="text" readonly="t" name="mobile" id="mobile" value="0987654321 - Nov '23">
and for my friend Lea (I call her the "Lioness") I note her phone number ... and get back her phone number field correctly escaped:
<input type="text" readonly="t" autocomplete="off" name="phone" id="phone" value="0654321 - the "Lioness"">
Everything seems fine now, thanks again!
There's a feature to let multiple versions of Gauche coexist. However, it only works when they have different version numbers; I haven't bumped the version number from 0.9.14 yet, so you can't install 0.9.14 release and HEAD together.
But there have been quite a few changes, so I might bump it to 0.9.14-p1 or something. Once I do it, you can install HEAD with the same prefix, and gosh -v0.9.14 ...
would run the 0.9.14 release, while just gosh
would run the HEAD.
In fact, it is convenient that gosh -v0.9.14
always run the proper 0.9.14 release... I could immidately bump the version number with suffix after release so that it is always possible to distinguish official release and HEAD.
OK, thanks - I may try this in the future then!
There are still some issues with the rendering unfortunately! (while the escaping of values with double quotes is fixed now, as discussed above, thanks again):
Below are two little code snippets from the leanpub Alpine.js book https://leanpub.com/getting-started-alpine-js - to make them work, you'd have to either add a script tag
`(script (@
(defer "")
(src "https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js")
or otherwise download alpine.js - very simple beginner examples, i.e.: hiding/showing some content, and graying out some buttons depending on state.
But the (Makiki) rendering issue is visible even without installing Alpine: (and I am by no means an Alpine expert: a beginner really - but the rendering issue is easily seen):
In the first example:
(div (@
(x-data "{ open: false }")
)
(button (@
(x-on:click "open=!open")
)
"Give me a click"
)
(div (@ (x-show "open"))
"Hidden by default"
))
the button is rendered only with
<button click="open=!open">Give me a click</button>
were really it should be rendered as
<button x-on:click="open=!open">Give me a click</button>
i.e. the x-on:
part of the attribute is cut off.
In this case there is a simple fix for me: use @click
instead
(button (@
(@click "open=!open")
)
which works just as well, and is rendered fine. - However: with my own renderer sxml->html-string (as above), I don't have this issue at all: the button is rendered as
<button x-on:click="open=!open">Give me a click</button>
as it should be.
The second example is similar:
(div (@
(x-data "{ woman: true }")
)
(button (@
(x-bind:disabled "woman==false")
(x-on:click "woman=false")
)
"Man")
(button (@
(:disabled "woman==true")
(@click "woman=true")
)
"Woman")
)
the buttons are rendered only as
<button disabled="woman==false" click="woman=false">Man</button>
<button disabled="woman==true" @click="woman=true">Woman</button>
i.e. the x-bind:
and x-on:
part of the attributes are cut off, resp for the second button: the colon before disabled.
With my own sxml->html-string renderer I don't have these issues: no part of any attribute is cut off i.e. - and this works thus: clicking on Man greys out Man (and makes Woman clickable), and vice versa - rendered as:
<div x-data="{ woman: true }">
<button x-bind:disabled="woman==false" x-on:click="woman=false">Man</button>
<button :disabled="woman==true" @click="woman=true">Woman</button>
</div>
Is there something special about these attributes with colons ?
If you need I can send you a complete working example - not now though (as I am busy) - but later.
Thanks again (in advance). - Andreas
I see, that's another quirk from the fact that HTML is not XML. SXML is strictly based on XML and as such, x-on:click
is understood as click
in the XML namespace x-on
. SXML core has mechanism to deal with namespaces, but it looks like sxml:sxml->html
was written without much thought about this issue. It blindly drops namespaces. (srl:sxml->html
does not drop namespace info, but the way it emits output won't help either, although it is a valid XML).
I think it is wrong to recognize XML namespeace prefix within HTML. I can fix sxml:sxml->html
.
I wonder why I haven't been bitten by this... Maybe I've used text.html-lite
when I used JS framework that asks a colon in attribute names. Anyway, it's better that sxml.tools
can handle stuff seamlessly.
Fix pushed in Gauche.
The version of Gauche HEAD is also bumped to 0.9.14-p1
, so you can install it with the same prefix with the released version of 0.9.14
if you like. If you run just gosh
, it will run whatever you installed last. You can specify the version with -v
option, e.g . -v0.9.14
.
OK, thanks a lot! - I will have a look soon (being busy still). - And I meant to answer earlier: namespaces ... - I understand / makes sense! ...
Hm, I am struggling with the installation / build steps (again) - and have at some point decided to start anew - with the steps that had previously/above worked for me (i.e. from a completely clean environment):
have removed my target directory ~/opt/devgauche
rm -rf ~/opt/devgauche
have installed a release gauche (0.9.14) therein anew:
bash ./get-gauche.sh --auto --prefix ~/opt/devgauche
so far, so good:
~/opt/devgauche/bin/gosh -V
shows version 0.9.14
, and - as previously - I have this in my path:
export PATH=$PATH:$HOME/opt/devgauche/bin
so this is the gauche that's being used for the next build steps:
And after some messing around in my git repository (in ~/tmp/devgauche), have decided to completely clean up everything therein, starting from a pristine HEAD checkout i.e.
I did
git fetch
git merge origin/master
and then therein
make distclean
and I git restored ...
some build artefacts from previous builds: gc/ltmain.sh
, gc/m4/libtool.m4
, gc/m4/ltversion.m4
- so now my git repository is completely clean - and up to date (shows in green in my bash prompt):
rx@softland {master} ~/tmp/devgauche $ git status
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
rx@softland {master} ~/tmp/devgauche $
Therein I start
./DIST gen
./configure --prefix ~/opt/devgauche --with-tls=none
and at the end of this configure run I see: we are about to build 0.9.14-p1 - Fine!
...
config.status: creating Makefile
config.status: creating bdw-gc.pc
config.status: creating include/config.h
config.status: executing depfiles commands
config.status: executing libtool commands
config.status: executing default commands
This Gauche has been configured with the following parameters:
version: 0.9.14-p1
documentation: Yes
slib: /usr/local/slib
thread: pthreads
tls/ssl:
CA store: check
optional modules: gdbm zlib
rx@softland {master} ~/tmp/devgauche $
So there we go:
make
and this make
is busy compiling for some time ..., but then stops with:
gcc -DHAVE_CONFIG_H -I. -I. -I./../gc/include -I../gc/include `./get-atomic-ops-flags.sh .. .. --cflags` -g -O2 -Wall -Wextra -Wno-unused-label -fPIC -fomit-frame-pointer -c test-extra.c
GAUCHE_LOAD_PATH="" GAUCHE_DYNLOAD_PATH="" "/home/rx/opt/devgauche/bin/gosh" -v:0.9.14 -l./preload -I../src -I../lib -I../lib -I. `cat ./features.flags` ../lib/tools/precomp -D LIBGAUCHE_BODY libextra.scm
gosh: "ERROR": cannot find "gauche/collection" in ("/home/rx/opt/devgauche/share/gauche-0.98/site/lib" "/home/rx/opt/devgauche/share/gauche-0.98/0.9.14-p1/lib")
make[1]: *** [Makefile:29: libextra.c] Error 1
make[1]: Leaving directory '/home/rx/tmp/devgauche/src'
make: *** [Makefile:47: all] Error 1
rx@softland {master} ~/tmp/devgauche $
I.e. gauche/collection
is searched in /home/rx/opt/devgauche/share/gauche-0.98/0.9.14-p1/lib
- well there is none yet: we are only building this 0.9.14-p1 after all!
There is a gauche collection in /home/rx/opt/devgauche/share/gauche-0.98/0.9.14/lib
, but I have a hard time telling configure and/or make
to use this path: I have tried
configure ... --with-local=/home/rx/opt/devgauche/share/gauche-0.98/0.9.14 ...
and various other configurations - but there are so many variables to set: LT_SYS_LIBRARY_PATH / GAUCHE_LOAD_PATH / GAUCHE_DYNLOAD_PATH as environment variables before configure / make / ... ? - as configure options ? - I am a bit at a loss here.
(I hope that my above explanations are reasonably clear: if you would follow them: you would run into the same dead end, I guess).
And some some advice is appreciated thus!
Thanks!
to summarise: for me the (installation) situation was easier, when both: the latest release (that I could install with get-gauche.sh) and git HEAD were at the same version (0.9.14 till recently): now that HEAD has moved forward to -p1, I cannot install HEAD any more. I see that one older -p1 version was also installable with get-gauche.sh, namely 0.9.11-p1
get-gauche.sh --list
....
0.9.11-p1
0.9.11
Maybe it would be possible to make 0.9.14-p1 get-gauche.sh installable as well? (other install suggestions / advice welcome, of course). In the worst case I will have to wait: for HEAD and the latest release being at the same version number again. - Thanks.
Hmm, that shouldn't be the case, I need to take a look. Meanwhile, I made 0.9.14-p1 available for get-gauche. Currently I need to package it manually, but maybe I can set up an automated process to make bleeding-edge nightly build available for get-gauche.
OK, thanks a lot: I will try with 0.9.14-p1 via get-gauche then next (and then I should be able to install HEAD as well) - That worked for me at least when both were at 0.9.14.
When you take the time then to take a closer look: I tried to write down my exact steps above in as clear a manner as possible (starting from a clean checkout etc.) - adjust them to your liking, of course: call my ~/opt/devgauche directory just targetdir etc. - The INSTALL.adoc and HACKING.adoc documents talk in general terms about how to proceed, but here is my step-by-step attempt to get from zero to a working HEAD gauche on Linux (maybe there is just some tiny parameter / config setting / env param missing somewhere?) Thanks again.
So I have been able to successfully install HEAD now (with first installing
./get-gauche.sh --version 0.9.14-p1 --auto --prefix ~/opt/devgauche
and then
./configure --prefix ~/opt/devgauche --with-tls=none
make
make check
make install
thanks!
And the attributes (Alpine.js examples) are rendered just fine!
Thanks again.
PS: I have edited this comment: originally I had issues still. - But that was my bad really: I had two servers running at the same time (one of them the older version still). - I hope, you got to see the right message: that everything is fine now, indeed. Many thanks, again.
OK, another one - and it's late into the night in London currently (and I am kind of exhausted) - thus bear with me (and this is not a polished bug report thus), but I want to get this out nevertheless:
Makiki is Great! Many thanks, again. - I am just not convinced that the current way of rendering the html tree with functions
tree->string & sxml:sxml->html
is the best one possible (and tree->string from text.tree is just calling write-tree with a string output port, as I have learned from the Gauche-Manual. And we have just recently discussed them here in the issue tracker ...)
Now the issue I have with them is, that attributes there are rendered in single quotes throughout: just look at the source code of any (simple) rendered page (rendered with):
(respond/ok req blahblah)
and you can see (you know) it looks like this:
Now comes the problem: I have a (very simple) contact database application: one can see a list of contacts, view the details of one or the other contact, edit them (or similarly add new contacts) - nothing complicated: To make it simple: say one contact has only three fields: first name, last name , and a mobile number.
Thus the edit form has some input fields:
in detail:
and likewise for lastName, and mobile. - These are form fields (within a form element, which is then sent with a post request to the server ... you know all this! that's basic stuff). the server notes the changes, and responds with another page: these contact details in a view page. (such a view page is very similar, just with readonly='t' for the input fields).
Now I have a bad habit of taking notes in form fields, likes so: for the mobile number I note not only the number, but also when / where I got this number I enter into this text input field
I.e. I type (among other characters) a literal single quote in my (mobile number) form field. - I save it (it's sent to the server, the server notes the changes, and sends back the corresponding view page:
The page sent back looks strange - and not too surprisingly: I look at its source:
See the problem?
I have thus swapped out tree->string & sxml:sxml->html (for now), and replaced it with some other function that works for me - from some blog post of David Thompson originally (then adapted for my needs in Guile at the time, and now ported to Gauche,): I am attaching the module below : oursxml2html.scm (and I have written a few more words in the comments therein).
Now instead of calling
for rendering some sexp tree blablah I just call:
i.e. I strip off the sxml root node with cdr (as I don't want to change my application too much), and then I do my own (David Thompson's) rendering: And (as is usual anyway, I guess?): double quotes are used for attributes. - All the pages render fine, and the above issue is gone.
I guess you can reproduce the above issue on your own. - If not: let me know, and then I can provide a complete example: but I will want to strip down my code to its essential core (thus not here/now).
Thus at this time only the oursxml2html rendering module with function sxml->html-string therein below. - If you really want to use this code then: I guess you should test it more thoroughly / give it some polish (and maybe see with regards to licensing: maybe contact David).
OK ... I just tried to upload it - but I got a message: we don't support that file type (a scheme file i.e.)... Thus I am pasting it in here - if that's getting too complicated: I can send it by e-mail
Thanks, Andreas