Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

html rendering - as currently in makiki: with single quotes throughout - causes issues - solution provided as well #11

Open
reuleaux opened this issue Mar 23, 2024 · 22 comments

Comments

@reuleaux
Copy link

reuleaux commented Mar 23, 2024

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:

<html lang='en'><head><meta charset='utf-8'> ...</html>

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:

first name: 
last name:
mobile:

in detail:

<input type='text' name='firstName' id='firstName' value='Paul'>

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

mobile:
0987654321 - from Blah, in November '23

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:

<input type='text' readonly='t' name='mobile' id='mobile' value='0987654321 - from Blah, in November '23'>

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

(respond/ok req blahblah)

for rendering some sexp tree blablah I just call:

(use oursxml2html :only (sxml->html-string))


;; and deep inside a handler:

	    (respond/ok req
	      (format #f "~a~%~a"
		"<!doctype html>"
		($ sxml->html-string $ cdr blahblah)
		))

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

;; This is from an article / blog by David Thompson (of Guile fame):
;; https://dthompson.us/rendering-html-with-sxml-and-gnu-guile.html

;; modifications (for Gauche, among others) & comments are mine (Andreas Reuleaux)


;; Apparently there are different versions of these rendering html functions:

;; (1)
;; the original article contained a slightly more powerful version
;; as I remember: also providing for unescaped / raw html output.

;; (2)
;; whereas the version found in Haunt (David's static website generator in Guile)
;; was less powerful: did not take raw html into account.

;; that's why I looked into this in more detail at the time - in Guile:
;; I switched raw html rendering back on again.

;; that's why there are two functions: sxml->html and sxml->html2
;; at the end (with and wo/ raw ...)


;; But all this raw rendering is of no importance here for Gauche:
;; (it's just an introduction: why I looked into that html rendering in
;; more detail at the time).

;; Now having spent some time with this rendering by hand (as by David's functions below),
;; taking them to Gauche now, was not too difficult: (paragraphs should be swapped: 
;; continue reading below with basically) ...

;; Also, now that I look at it again: I see that there is also a means to take
;; care of (render) a doctype declaration somehow: I don't know how it works
;; (have tried this at the time, but not now again), as I am rendering the doctype separately now: like so
;; typically:

	    	  	  
;; (respond/ok req
;;   (format #f "~a~%~a"
;; 	"<!doctype html>"
;; 	($ sxml->html-string $ cdr (edit c))
;; 	))

;; Thus maybe this doctype stuff below can be removed? - likewise the raw html stuff
;; that's rarely ever needed...


;; basically  - to make it work with Gauche -

;; * I had to get rid of one nested function definition
;;  in string->escaped-html below: turned the inner function into a let & lambda

;; * and have used the Gauche way of getting (asking about) elements in a hash table



;; Ah, and as I remember: the module did provide a function pair: ...sxml->xml & sxml->html - I have split this in two,
;; and am only covering the sxml->html part here.

;; That's it: sxml->html-string renders all my html beautifully now,
;; and without any issues





(define-module oursxml2html
  
  (use util.match)
  
  (export sxml->html-string)

  )


(select-module oursxml2html)


;; I guess we need this
(define *unspecified* '|*unspecified*|)



;; as I understand: these  have an impact of how empty elements (with no children) are rendered
;; (being in this list or not i.e.) - yet to try out in more detail.

(define %void-elements
  '(area
    base
    br
    col
    command
    embed
    hr
    img
    input
    keygen
    link
    meta
    param
    source
    track
    wbr))



(define (void-element? tag)
  "Return #t if TAG is a void element."
  (pair? (memq tag %void-elements)))

(define %escape-chars
  (alist->hash-table
   '((#\" . "quot")
     (#\& . "amp")
     (#\< . "lt")
     (#\> . "gt"))))



;; two modifications from the guile version:
;; (1) could not define an inner function - thus a lambda, let-bound instead
;; (2) have used the gauche way of hash referencing: hash-table-get with a default value #f

(define (string->escaped-html s port)
  "Write the HTML escaped form of S to PORT."
  (let ([escape (^c
		  (let (
			 [escaped (hash-table-get %escape-chars c #f)]
			 )
		   (if escaped
		     (format port "&~a;" escaped)
		     (display c port))))])
    (string-for-each escape s)))


(define (object->escaped-html obj port)
  "Write the HTML escaped form of OBJ to PORT."
  (string->escaped-html
   (call-with-output-string (cut display obj <>))
   port))

(define (attribute-value->html value port)
  "Write the HTML escaped form of VALUE to PORT."
  (if (string? value)
      (string->escaped-html value port)
      (object->escaped-html value port)))

(define (attribute->html attr value port)
  "Write ATTR and VALUE to PORT."
  (format port "~a=\"" attr)
  (attribute-value->html value port)
  (display #\" port))

(define (element->html tag attrs body port)
  "Write the HTML TAG to PORT, where TAG has the attributes in the
list ATTRS and the child nodes in BODY."
  (format port "<~a" tag)
  (for-each (match-lambda
             ((attr value)
              (display #\space port)
              (attribute->html attr value port)))
            attrs)
  (if (and (null? body) (void-element? tag))
      (display " />" port)
      (begin
        (display #\> port)
        (for-each (cut sxml->html <> port) body)
        (format port "</~a>" tag))))





(define (doctype->html doctype port)
  (format port "<!DOCTYPE ~a>" doctype))

;; orig - as from haunt

(define (sxml->html tree :optional (port (current-output-port)))
  "Write the serialized HTML form of TREE to PORT."
  (match tree

    [() *unspecified*]

    [('doctype type)
      (doctype->html type port)]

    [((? symbol? tag) ('@ attrs ...) body ...)
      (element->html tag attrs body port)]

    [((? symbol? tag) body ...)
      (element->html tag '() body port)]
    
    [(nodes ...)
      (for-each (cut sxml->html <> port) nodes)]

    [(? string? text)
      (string->escaped-html text port)]

    ;; Render arbitrary Scheme objects, too.
    (obj (object->escaped-html obj port))))



;; as from the article
;; https://dthompson.us/rendering-html-with-sxml-and-gnu-guile.html
;; w/ raw


(define (sxml->html2 tree :optional (port (current-output-port)))
 "Write the serialized HTML form of TREE to PORT."
 (match tree
   (() *unspecified*)
   (('doctype type)
    (doctype->html type port))

   ;; Unescaped, raw HTML output
   (('raw html)
    (display html port))

   (((? symbol? tag) ('@ attrs ...) body ...)
    (element->html tag attrs body port))
   (((? symbol? tag) body ...)
    (element->html tag '() body port))
   ((nodes ...)
    (for-each (cut sxml->html <> port) nodes))
   ((? string? text)
    (string->escaped-html text port))
   ;; Render arbitrary Scheme objects, too.
   (obj (object->escaped-html obj port))))


(define (sxml->html-string sxml)
  "Render SXML as an HTML string."
  (call-with-output-string
   (lambda (port)
     (sxml->html sxml port))))


@shirok
Copy link
Owner

shirok commented Mar 23, 2024

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.

@reuleaux
Copy link
Author

reuleaux commented Mar 23, 2024

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 - &quot;the Lioness&quot;" />

without me having to think about any escaping.

@reuleaux
Copy link
Author

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)

@reuleaux
Copy link
Author

reuleaux commented Mar 24, 2024

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)
  )

@shirok
Copy link
Owner

shirok commented Mar 24, 2024

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.

@reuleaux
Copy link
Author

OK, Great! - And thanks for this explanation!

shirok added a commit to shirok/Gauche that referenced this issue Mar 25, 2024
@shirok
Copy link
Owner

shirok commented Mar 25, 2024

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?

@reuleaux
Copy link
Author

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.

@reuleaux
Copy link
Author

reuleaux commented Mar 25, 2024

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.

@shirok
Copy link
Owner

shirok commented Mar 25, 2024

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.

@reuleaux
Copy link
Author

reuleaux commented Mar 26, 2024

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 &quot;Lioness&quot;">

Everything seems fine now, thanks again!

@shirok
Copy link
Owner

shirok commented Mar 26, 2024

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.

@reuleaux
Copy link
Author

OK, thanks - I may try this in the future then!

@reuleaux
Copy link
Author

reuleaux commented Mar 27, 2024

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/[email protected]/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

@shirok
Copy link
Owner

shirok commented Mar 27, 2024

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.

shirok added a commit to shirok/Gauche that referenced this issue Mar 27, 2024
The original sxml-tools is a simple wrapper to treat SXML as html
tree.  But HTML is not exactly XML, and requires more specific handling.

- HTML doesn't have namespaces.  So, if an attribute name contains a colon,
  it's a part of the name; render it as is.
- HTML doesn't have self-closing elements (but it has void elements).
  So, non-void elements with empty content should be rendered
  as <foo></foo>.

shirok/Gauche-makiki#11
@shirok
Copy link
Owner

shirok commented Mar 27, 2024

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.

@reuleaux
Copy link
Author

OK, thanks a lot! - I will have a look soon (being busy still). - And I meant to
answer earlier: namespaces ... - I understand / makes sense! ...

@reuleaux
Copy link
Author

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!

@reuleaux
Copy link
Author

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.

@shirok
Copy link
Owner

shirok commented Mar 28, 2024

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.

@reuleaux
Copy link
Author

reuleaux commented Mar 28, 2024

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.

@reuleaux
Copy link
Author

reuleaux commented Mar 29, 2024

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.

wip-sync pushed a commit to NetBSD/pkgsrc-wip that referenced this issue Jul 12, 2024
Changelog:

2024-04-23  Shiro Kawai  <[email protected]>

	* Release 0.9.15

	* tools/tls/Makefile.in: Downgraded MbedTLS-internal version to
	  3.5.2, since 3.6.0 has an issue on MinGW.  See
	  shirok/Gauche#1021
	* tools/tls/process-config.sh: Need to tweak MinGW i686 build.

	* lib/gauche/configure.scm (cf-call-with-cpp): Added.

	* src/genconfig.in: Add --cpp and --cppflags for C preprocessor
	  configration.  Useful for 'configure' script.

2024-04-17  Shiro Kawai  <[email protected]>

	* src/libnum.scm (sin etc.): Let them always return inexact numbers.
	  Previously we had (sin #e0) => #e0 etc., but it's not necessary,
	  and diverging from real-sin etc. isn't desirable.
	  (atan): Fix the special case when both args are zero.

2024-04-16  Shiro Kawai  <[email protected]>

	* ext/tls/tls-mbed.c (Scm_Init_rfc__tls__mbed): Add missing
	  psa_crypto_init() to fix TLS handshake error.
	  shirok/Gauche#1018

	* tools/tls/Makefile.in (include/mbedtls): Bumped MbedTLS version
	  to 3.6.0 to fetch with --with-tls=mbedtls-internal.

2024-04-15  Shiro Kawai  <[email protected]>

	* src/system.c (Scm_SysExec),
	  src/libsys.scm (%sys-escape-windows-command-line): When a BAT file
	  is run via CreateProcess, Windoes uses different rules to parse
	  the command line, causing a security risk.  We reject 'unsafe'
	  characters in the command line arguments if BAT file is the program
	  to run.  See CVE-2024-3566
	  https://nvd.nist.gov/vuln/detail/CVE-2024-3566

2024-04-10  Shiro Kawai  <[email protected]>

	* DIST, test/standalone.scm: Run build-standalone with the installed
	  Gauche during DIST self-host-test.
	  This can catch the issue like
	  shirok/Gauche#1013

	* src/gauche.h: Do not include gauche/priv/configP.h, even if it is
	  #ifdef'ed.  It is simply wrong to include a private header from a
	  public header.  Instead, it should be included from each
	  individual source files.
	  Cf. shirok/Gauche#1013

2024-04-08  Shiro Kawai  <[email protected]>

	* ext/sxml/sxml-tools.scm.in (sxml:sxml->xml): Replace original proc
	  to handle namespaces.

2024-04-07  Shiro Kawai  <[email protected]>

	* src/libnum.scm (*, +): When used as unary operators on non-number
	  object, delegate it to object-* or object-+.  For the practical
	  purposes, they should return the argument as is; their existence
	  is the assertion that such opeartion is valid.    We used to return
	  the argument as is, but that may miss errors.  Just in case if
	  existing code depends on the old behavior, we issue a warning
	  and return the argument if there's no unary method defined on
	  the argument's class.
	  shirok/Gauche#1012

2024-04-05  Shiro Kawai  <[email protected]>

	* src/libbox.scm (unbox, unbox-value): Associate setters.  Now
	  you can say (set! (unbox <box>) <value>) etc.

	* lib/gauche/cgen/cise.scm (<cise-env>): Use box for decls. Since
	  a new inner env may be created during recursion, we need an
	  indirection so that decls pushed into the inner env won't be lost.

2024-04-04  Shiro Kawai  <[email protected]>

	* src/string.c (string_putc): Buffer size too short.
	  Fix from NIIBE Yutaka.

	* src/gauche/priv/arith.h (SADDOV): Avoid undefined behavior of
	  signed integer overflow.  Fix from NIIBE Yutaka.

2024-04-03  Shiro Kawai  <[email protected]>

	* src/list.c: Ensure statically allocated ExtendedPairDescriptor
	  is aligned in 8 byte boundary. It should be treated the same
	  as ScmClass because of tagged pointer.
	  Original fix from NIIBE Yutaka.

	* lib/srfi/238.scm: Added.

2024-04-01  Shiro Kawai  <[email protected]>

	* lib/srfi/64.scm: Changed integration to gauche.test.  Instead of
	  having a specific runner to bridge to gauche.test, we now bridge
	  regardless of the test runner.  This actually reveled some bugs
	  that have been overlooked (because it was reported only by the
	  srfi-64 test runner and not by gauche.test).
	  shirok/Gauche#1010

	* test/include/srfi-194-zipf-test.scm: Loosened tolerance of
	  chi^2 test a bit.  It is statistical tests and we need some
	  more room of statistical deviation.

	* lib/scheme/mapping.scm (%mapping-cmp),
	  lib/scheme/mapping/hash.scm (%hashmap-cmp): When given mappings
	  have different comparators, we should return #f, instead of
	  "cannot compare" error.

	* lib/srfi/235.scm (disjoin): Fix when a predicate created with
	  disjoin is given no arguments.  It is actually not specified
	  in SRFI text.  The test in srfi repo returns #t for it.

2024-03-29  Shiro Kawai  <[email protected]>

	* lib/gauche/test/generative.scm: Removed in favor of upcoming srfi-252.

2024-03-27  Shiro Kawai  <[email protected]>

	* src/core.c (Scm_Init): Explicitly start marker threads.  Recent
	  bdwgc delays marker thread creation until the user creates the
	  first thread, by default.  See the discussion at
	  https://sourceforge.net/p/gauche/mailman/gauche-devel/thread/87r0fvd5bl.fsf%40karme.de/

	* ext/sxml/sxml-tools.scm.in: Fix sxml:attr->html and sxml:sxml->html
	  to handle HTML's diversion from XML properly.  Specifically,
	  - Do not treat colons in attribute names as namespace prefix
	  - Do not emit self-closing tag for non-void elements with empty
	  content.
	  shirok/Gauche-makiki#11

2024-03-25  Shiro Kawai  <[email protected]>

	* Bumped version number to 0.9.14-p1
	  We're not quite ready for prerelease of next version (presumably
	  1.0_pre1), but we have enough changes since the last release
	  so we want to distinguish HEAD from the offical release.

	* lib/data/random.scm (reals-between$): Fix overflow and precision loss
	  shirok/Gauche#1000

2024-03-24  Shiro Kawai  <[email protected]>

	* ext/sxml/sxml-tools.scm.in (sxml:attr->xml, sxml:attr->html):
	  Override to fix shortcomings of the original sxml that attribute
	  values are not quoted.
	  Related: shirok/Gauche-makiki#11

2024-03-23  Shiro Kawai  <[email protected]>

	* src/gauche-package.in (compile): Support --c++ option.  This tells
	  precomp to generate *.cpp file.  Later, we may switch precomp mode
	  to support C++ specific stuff.

	* lib/gauche/cgen/unit.scm (<cgen-unit>): Add 'language slot;
	  now it generate *.cpp if the language is 'c++.

	* src/libtype.scm (<Assortment>): Replace <Singleton> and
	  <Singleton-set> with <Assortment>.  With this word, we can
	  use the same type for the union of singletons, eliminating
	  the need to have separate 'set' type.
	  Cf. shirok/Gauche#906

2024-03-22  Shiro Kawai  <[email protected]>

	* src/gauche.h, src/gauche/float.h: Ensure include complex.h outside
	  of extern "C" linkage.  OSX clang doesn't like otherwise if
	  we include gauche.h to C++ source.
	  https://github.com/shirok/Gauche/1006

2024-03-21  Shiro Kawai  <[email protected]>

	* src/gauche-package.in (compile),
	  lib/gauche/package/compile.scm (gauche-package-compile):
	  Add --srcdir option for out-of-tree compilation.

	* libsrc/file/util.scm (build-path): Allow #f in the path components
	  (interpreted as ".") for the convenience.

2024-03-20  Shiro Kawai  <[email protected]>

	* lib/gauche/cgen/stub.scm (.include): Split .include in stub toplevel
	  and CiSE .include.  Stub .include is emitted to decl section,
	  while CiSE .include is emitted in place (body section).
	  This may be potentially confusing, and good documentation is desired.
	  See shirok/Gauche#1003 for the background
	  of this change.

2024-03-19  Shiro Kawai  <[email protected]>

	* lib/gauche/cgen/cise.scm (cise-omit-source-line): Change
	  the parameter cise-emit-source-line to cise-omit-source-line,
	  flipping the logic.  This aligns better with the options
	  (e.g. --no-line of `gauche-package compile`).

	* lib/data/range.scm (%appended-range-index): Bug in binary search.
	  Patch from @gengar shirok/Gauche#1004

2024-03-18  Shiro Kawai  <[email protected]>

	* lib/gauche/cgen/precomp.scm: Take the default value of
	  omit-line-directives keyword arg from the parameter
	  cise-emit-source-info, so that the parameter settings by the
	  the higher layer (e.g. 'gauche-package compile') is reflected.

2024-03-16  Shiro Kawai  <[email protected]>

	* lib/gauche/listener.scm (listener-read-handler): Fixed a bug revealed
	  by the last fix.  string-incomplete->complete is used in a
	  meaningless way.

	* src/string.c (Scm_StringRefCursor): Fix a bug that leaked
	  #<unbound> to the Scheme world when an incomplete string is given.
	  It could be exhibited by this:
	    (let1 z #**"\xe1;"
	      (string-ref z (string-index->cursor z 0)))
	  Now it properly raises an error.

2024-03-15  Shiro Kawai  <[email protected]>

	* lib/srfi/215.scm: Supported.  Contribution from Antero Mejr.

2024-03-12  Shiro Kawai  <[email protected]>

	* lib/data/random.scm (reals-power-law$): Added.

2024-03-11  Shiro Kawai  <[email protected]>

	* lib/data/random.scm (finite-flonums$): Added.

2024-03-10  Shiro Kawai  <[email protected]>

	* doc/Makefile.in: Use install-info if it's available, and DESTDIR
	  is not used. shirok/Gauche#988

2024-03-09  Shiro Kawai  <[email protected]>

	* examples/mqueue-cpp: Update to use modern way (no stub file).

	* ext/windows: Replace *.stub for *.scm.

2024-03-08  Shiro Kawai  <[email protected]>

	* lib/gauche/cgen/cise.scm: Handle C++ new and delete as operators.
	  (cise-render-identifier): Allow C++ namespace qualified identifiers.

2024-03-05  Shiro Kawai  <[email protected]>

	* src/libnum.scm (greatest-positive-flonum): Add.  Also renamed
	  flonum-min-normalized and flonum-min-denormalized to
	  least-positive-normalized-flonum and least-positive-flonum.
	  They are consistent with {greatest|least}-fixnum.  We added
	  'positive' for clarity.  We dropped 'denormalized', since
	  the platform may not support denormalized flonums, and the
	  procedure returns normalized flonum in that case.

2024-03-04  Shiro Kawai  <[email protected]>

	* lib/gauche/package/compile.scm: Revert the idea of *.scm.c for
	  generated C files.  It messes up Makefile inference rules
	  (make thinks foo.scm should be regenerated if foo.scm.o is newer).
	  For the name conflicts, we can name the stub definition file as
	  foolib.scm, much like we've done with foolib.stub.  Now we can
	  do so because we split module definition file from stub definition
	  file.

	* lib/gauche/cgen/precomp.scm: Add support of in-module form.
	  For now, this form is valid only for precompilation; normal
	  compiler ignores it with warning.  It allows to switch modules
	  during precompilation like select-module, but the module
	  doesn't need to exist at the moment (it is created implicitly then).
	  It suppors precompiling sources with stubs separately from
	  the module definintion file.
	  Cf. shirok/Gauche#993

2024-03-02  Shiro Kawai  <[email protected]>

	* lib/gauche/package/compile.scm:
	  When 'gauche-package compile' receives *.scm file, we create
	  intermediate C file as *.scm.c, instead of *.c, for a module
	  may already have *.c with the same name.

2024-03-01  Shiro Kawai  <[email protected]>

	* examples/spigot: Update for modern way---no *.stub file, and *.scm
	  file to be precompiled.

	* lib/gauche/package/compile.scm (gauche-package-compile): Make sure
	  to pass DSO filename when '*.scm' is compiled with
	  'gauche-package compile'.  Without this fix, generated '*.sci'
	  file can't have a proper dynamic-load call.

2024-02-29  Shiro Kawai  <[email protected]>

	* src/compile-1.scm, src/compile-5.scm, src/libcode.scm, src/libtype.scm:
	  Carry procedure type of closures in $lambda-meta, instead of
	  pair attribute of the source form---using pair attr was a kludge.
	  The type is carried as <descriptive-type>.
	  It is eventually stored in <compiled-code>#signature-info,
	  and retrieved by compute-procedure-type (which is called from
	  procedure-type).
	  This allows argument type information of closures to be reflected
	  to its procedure-type.

2024-02-27  Shiro Kawai  <[email protected]>

	* src/libtype.scm (type?): Added.

2024-02-25  Shiro Kawai  <[email protected]>

	* lib/lang/asm/regset.scm: Added.

2024-02-20  Shiro Kawai  <[email protected]>

	* src/vm.c, src/libeval.scm: Remove Scm_VMInsnOffsets and
	  %vm-get-insn-offsets.  Add Scm_VMInsnAddress and %vm-get-insn-address.
	  This is an undocumented API change.

2024-02-18  Shiro Kawai  <[email protected]>

	* src/libexc.scm (print-additional-error-heading): Split auxiliary
	  info reporting from print-default-error-heading, so that it can be
	  used from other error reporters.
	* src/main.c (error_exit): When we exit during with -l or -e option,
	  use print-additional-error-heading to print additional information
	  (but not a stack trace).

2024-02-14  Shiro Kawai  <[email protected]>

	* lib/gauche/vm/insn-core.scm, src/code.c: Add 'obj+native'
	  instruction type, for JIT support.

2024-02-13  Shiro Kawai  <[email protected]>

	* src/code.c, src/vminsn.scm: Change operand type 'addr' to 'label',
	  to avoid confusion with the oncoming enhancement.
	  (This is an API change, though it hasn't been documented).

2024-02-12  Shiro Kawai  <[email protected]>

	* lib/gauche/cgen/cise.scm (asm): Add asm cise macro to generate
	  gcc inline assembly.

2024-02-10  Shiro Kawai  <[email protected]>

	* lib/srfi/247.scm: Add SRFI-247

2024-02-07  Shiro Kawai  <[email protected]>

	* libsrc/gauche/collection.scm (size-of): Missing size-of method
	  defintion specialized for hashtables and treemaps, causing
	  size-of on these objects O(n).
	  Cf. shirok/Gauche#987

2024-02-04  Shiro Kawai  <[email protected]>

	* lib/rfc/uri.scm (uri-decompose-query, uri-compose-query),
	  lib/rfc/http.scm (http-compose-query),
	  lib/www/cgi.scm (cgi-parse-parameters): Provide basic url query
	  utilities in rfc.uri, and define existing utils on top of them.

	* src/liblist.scm: Change optional argument order of new alist-*
	  procs.  It is easier to have key= argument first, to handle
	  variations.

2024-02-03  Shiro Kawai  <[email protected]>

	* src/liblist.scm (alist-merge): Added.
	  (alist-ref, alist-key, alist-adjoin, alist-update-in): Renamed
	  assoc-ref, rassoc-ref, assoc-adjoin, and assoc-update-in.
	  Old names are kept for the backward compatibility.
	  shirok/Gauche#985

2024-02-02  Shiro Kawai  <[email protected]>

	* libsrc/gauche/collection.scm (group-collection->alist): Added.

2024-01-31  Shiro Kawai  <[email protected]>

	* libsrc/rfc/822.scm (rfc822-header-ref*, rfc822-header-put): Added.

2024-01-29  Shiro Kawai  <[email protected]>

	* src/gauche-package.in: Add 'populate' subcommand.

	* lib/text/multicolumn.scm (layout-multicolumn): Fix the edge case
	  when the string list is empty.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants