Skip to content

Commit

Permalink
Merge branch 'master' of github.com:ocsigen/tyxml into 20230927_merge…
Browse files Browse the repository at this point in the history
…_master
  • Loading branch information
rand00 committed Sep 27, 2023
2 parents 90558cd + d291653 commit 155f1bf
Show file tree
Hide file tree
Showing 28 changed files with 401 additions and 90 deletions.
19 changes: 9 additions & 10 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,29 @@ jobs:
ocaml-compiler:
- 4.04.x
- 4.05.x
- 4.06.x
- 4.07.x
- 4.08.x
- 4.09.x
- 4.10.x
- 4.11.x
- 4.12.x
- 4.13.x
- 4.14.x
- 5.0.x
- 5.1.x
include:
- os: macos-latest
ocaml-compiler: 4.12.x
ocaml-compiler: 4.14.x
- os: windows-latest
ocaml-compiler: 4.12.x
ocaml-compiler: 4.14.x
- os: macos-latest
ocaml-compiler: 5.1.x

runs-on: ${{ matrix.os }}

steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: Use OCaml ${{ matrix.ocaml-compiler }}
uses: ocaml/setup-ocaml@v2
with:
ocaml-compiler: ${{ matrix.ocaml-compiler }}
dune-cache: true
opam-depext-flags: --with-test

- run: opam install . --deps-only --with-test
Expand Down
18 changes: 16 additions & 2 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
# NEXT
# 4.6.0

* Update for OCaml 5.0 and drop support for OCaml 4.2.0
(#312 by @rr0gi)

* Add additional variants to `linktype` for the `rel` attribute
(Leon @LogicalOverflow Vack)

* Expand options for `autocomplete` attribute on `<input>` elements
(#302 by Aron @aronerben Erben)

* Fix the SVG animation attributes `a_animation_values`, `a_keyTimes` and `a_keySplines`
to contain semicolon separated values.
Expand All @@ -10,10 +19,15 @@

* Add support for `dialog` element and `onclose` attribute
(#301 by Julien Sagot)

* Add an escape hatch for emitting attributes with non-standard names
in jsx or ppx code (a leading `_` character on attribute name)
(#295 Chas @cemerick Emerick)
* Add support for `type` attribute on `<script>` elements
(#293 by Ulrik @ulrikstrid Strid and Chas @cemerick Emerick)

* Add svg `fill-rule` attribute
(#294 by Eric @dedbox Griffis)

# 4.5.0

* Move all the PPXs to ppxlib
Expand Down
12 changes: 12 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Code of Conduct

This project has adopted the [OCaml Code of Conduct](https://github.com/ocaml/code-of-conduct/blob/main/CODE_OF_CONDUCT.md).

# Enforcement

This project follows the OCaml Code of Conduct [enforcement policy](https://github.com/ocaml/code-of-conduct/blob/main/CODE_OF_CONDUCT.md#enforcement).

To report any violations, please contact Jérôme
Vouillon, Raphael Proust, Vincent Balat, Hugo Heuzard and Gabriel
Radanne at <moderation [at] ocsigen [dot] org>
(or some of them individually).
21 changes: 21 additions & 0 deletions docs/manual-wiki/jsx.wiki
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,27 @@ version in <<a_api project="js_of_ocaml" subproject="js_of_ocaml-tyxml" | Js_of_

In each case, simply open the module and the JSX syntax will use it.

==@@id="unsafe"@@ "Unsafe" attributes

Some Javascript libraries and frameworks depend upon HTML markup that includes non-standard
attributes, which tyxml would usually reject. When constructing elements using tyxml's API directly,
the available workaround is to use the <<a_api text="Unsafe"|val Html_sigs.T.Unsafe>> constructors.
The same relaxed semantics can be had when using JSX by prefixing non-standard attribute names
with a leading underscore.

So, while this will fail:
<<code language="ocaml"|
let button = <button hx_post="/clicked" hx_swap="outerHTML">Click Me</button>
>>

This will not:
<<code language="ocaml"|
let button = <button _hx_post="/clicked" _hx_swap="outerHTML">Click Me</button>
>>

Such underscore-prefixed attributes are presumed to be strings, and are constructed using e.g.
<<a_api text="Unsafe.string_attrib"|val Html_sigs.T.Unsafe.string_attrib>>.

==@@id="tips"@@ Tips

It can sometime be necessary to disable the JSX syntax. For that purpose, simply use the toogle `[@tyxml.jsx false]` to turn the JSX on and off.
21 changes: 21 additions & 0 deletions docs/manual-wiki/ppx.wiki
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,27 @@ let my_div = [%html "<div id="my_id"></div>"]
val my_div : [> Html_types.div ] Html.elt
>>

==@@id="unsafe"@@ "Unsafe" attributes

Some Javascript libraries and frameworks depend upon HTML markup that includes non-standard
attributes, which tyxml would usually reject. When constructing elements using tyxml's API directly,
the available workaround is to use the <<a_api text="Unsafe"|val Html_sigs.T.Unsafe>> constructors.
The same relaxed semantics can be had when using the ppx by prefixing non-standard attribute names
with a leading underscore.

So, while this will fail:
<<code language="ocaml"|
[%html {|<button hx_post="/clicked" hx_swap="outerHTML">Click Me</button>|}]
>>

This will not:
<<code language="ocaml"|
[%html {|<button _hx_post="/clicked" _hx_swap="outerHTML">Click Me</button>|}]
>>

Such underscore-prefixed attributes are presumed to be strings, and are constructed using e.g.
<<a_api text="Unsafe.string_attrib"|val Html_sigs.T.Unsafe.string_attrib>>.

==@@id="let"@@ Let notation

It is also possible to use the ppx with the ##let## notation:
Expand Down
4 changes: 2 additions & 2 deletions dune-project
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
(synopsis "Common layer for the JSX and PPX syntaxes for Tyxml")
(depends
(ocaml
(>= 4.02))
(>= 4.03))
(alcotest :with-test)
(ppxlib
(>= 0.18))
Expand All @@ -76,7 +76,7 @@
"TyXML provides a set of convenient combinators that uses the OCaml type system to ensure the validity of the generated documents. TyXML can be used with any representation of HTML and SVG: the textual one, provided directly by this package, or DOM trees (`js_of_ocaml-tyxml`) virtual DOM (`virtual-dom`) and reactive or replicated trees (`eliom`). You can also create your own representation and use it to instantiate a new set of combinators.")
(depends
(ocaml
(>= 4.02))
(>= 4.03))
(alcotest :with-test)
(re
(>= 1.5.0))
Expand Down
2 changes: 1 addition & 1 deletion jsx/dune
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@
-open Ppxlib
-w "-9"
))
)
)
42 changes: 21 additions & 21 deletions jsx/tyxml_jsx.ml
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,30 @@ let is_jsx e =
in
List.exists f e.pexp_attributes

(* When dropping support for 4.02, this module can simply be deleted. *)
module String = struct
include String
let lowercase_ascii = String.lowercase [@ocaml.warning "-3"]
end
module Char = struct
include Char
let lowercase_ascii = Char.lowercase [@ocaml.warning "-3"]
end

let lowercase_lead s =
String.mapi (fun i c -> if i = 0 then Char.lowercase_ascii c else c) s

let to_kebab_case name =
let length = String.length name in
if length > 5 then
let first = String.sub name 0 4 in
match first with
| "aria"
| "data" ->
first ^ "-" ^ lowercase_lead (String.sub name 4 (length - 4))
| _ -> name
else
name
let to_kebab_case =
let open Re in
let camelPat = Posix.compile_pat "[A-Z]" in
let underscore = compile @@ char '_' in
let prefixes = Perl.compile_pat {|^(data_?|aria_?)(.+)|} in
fun name ->
let kebab string =
replace camelPat ~f:(fun g -> "-" ^ Group.get g 0) string
|> String.lowercase_ascii
|> replace_string underscore ~by:"-" in
match exec_opt prefixes name with
| None ->
if name.[0] == '_'
(* need to keep the leading underscore, as that's what the syntax support keys
off of to know to use Unsafe.string_attrib *)
then "_" ^ kebab @@ String.sub name 1 (String.length name - 1)
else name
| Some g ->
let prefix = String.sub name 0 4 in
let suffix = kebab @@ Group.get g 2 in
prefix ^ (if suffix.[0] == '-' then "" else "-") ^ suffix

let make_attr_name name =
let name =
Expand Down
21 changes: 17 additions & 4 deletions lib/html_f.ml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ struct
| `Url_width of uri * Html_types.number
| `Url_pixel of uri * Html_types.float_number ]


type 'a attrib = Xml.attrib

let to_xmlattribs x = x
Expand Down Expand Up @@ -256,7 +255,7 @@ struct
let a_method x =
user_attrib C.string_of_big_variant "method" x

let a_formmethod = a_method
let a_formmethod x = user_attrib C.string_of_big_variant "formmethod" x

let a_enctype = string_attrib "enctype"

Expand Down Expand Up @@ -285,7 +284,7 @@ struct
user_attrib C.string_of_referrerpolicy "referrerpolicy" x

let a_autocomplete x =
user_attrib C.onoff_of_bool "autocomplete" x
user_attrib C.string_of_autocomplete "autocomplete" x

let a_async =
constant_attrib "async"
Expand Down Expand Up @@ -887,19 +886,27 @@ struct
| `Author -> "author"
| `Bookmark -> "bookmark"
| `Canonical -> "canonical"
| `Dns_prefetch -> "dns-prefetch"
| `External -> "external"
| `First -> "first"
| `Help -> "help"
| `Icon -> "icon"
| `Index -> "index"
| `Last -> "last"
| `License -> "license"
| `Manifest -> "manifest"
| `Me -> "me"
| `Modulepreload -> "modulepreload"
| `Next -> "next"
| `Nofollow -> "nofollow"
| `Noreferrer -> "noreferrer"
| `Noopener -> "noopener"
| `Noreferrer -> "noreferrer"
| `Opener -> "opener"
| `Pingback -> "pingback"
| `Preconnect -> "preconnect"
| `Prefetch -> "prefetch"
| `Preload -> "preload"
| `Prerender -> "prerender"
| `Prev -> "prev"
| `Search -> "search"
| `Stylesheet -> "stylesheet"
Expand Down Expand Up @@ -1121,6 +1128,12 @@ struct
in
String.concat ", " (List.map f l)

let string_of_autocomplete (l : Html_types.autocomplete_option) =
match l with
| `On | `Tokens [] -> "on"
| `Off -> "off"
| `Tokens strs -> String.concat " " strs

end

module Make
Expand Down
11 changes: 7 additions & 4 deletions lib/html_sigs.mli
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,8 @@ module type T = sig

val a_allowpaymentrequest : unit -> [> | `Allowpaymentrequest] attrib

val a_autocomplete : (bool[@onoff]) wrap -> [> | `Autocomplete] attrib
val a_autocomplete : autocomplete_option wrap -> [> | `Autocomplete] attrib
(** @see <https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete> autocomplete documentation. *)

val a_async : unit -> [> | `Async] attrib

Expand Down Expand Up @@ -502,9 +503,7 @@ module type T = sig
[< | `Get | `Post] wrap -> [> | `Method] attrib

val a_formmethod :
[< | `Get | `Post] wrap -> [> | `Method] attrib
[@@ocaml.deprecated "Use a_method"]
(** @deprecated Use a_method *)
[< | `Get | `Post] wrap -> [> | `Formmethod] attrib

val a_multiple : unit -> [> | `Multiple] attrib

Expand Down Expand Up @@ -1011,6 +1010,7 @@ module type T = sig

val textarea :
([< | textarea_attrib], [< | textarea_content_fun], [> | textarea]) unary
[@@reflect.element "textarea"]

val keygen : ([< | keygen_attrib], [> | keygen]) nullary

Expand Down Expand Up @@ -1255,6 +1255,9 @@ module type Wrapped_functions = sig
val string_of_srcset :
([< image_candidate] list, string) Xml.W.ft

val string_of_autocomplete :
(Html_types.autocomplete_option, string) Xml.W.ft

val string_of_step : (float option, string) Xml.W.ft

val unoption_string : (string option, string) Xml.W.ft
Expand Down
Loading

0 comments on commit 155f1bf

Please sign in to comment.