diff --git a/doc/RF6_XR_Fragments.png b/doc/RF6_XR_Fragments.png index 128e19e..d8b8f89 100644 Binary files a/doc/RF6_XR_Fragments.png and b/doc/RF6_XR_Fragments.png differ diff --git a/doc/RFC_XR_Fragments.html b/doc/RFC_XR_Fragments.html index 6e2f70f..b1939ea 100644 --- a/doc/RFC_XR_Fragments.html +++ b/doc/RFC_XR_Fragments.html @@ -320,8 +320,8 @@ That way, if the link gets shared, the XR Fragments implementation at http W3C Media Fragments media fragment -#t=0,2 #xywh -play/loop 3D animation from 0 seconds till 2 seconds +#t=0,2&loop +play (and loop) 3D animation from 0 seconds till 2 seconds @@ -448,6 +448,14 @@ That way, if the link gets shared, the XR Fragments implementation at http #foo=bar sets URI Template variable foo to the value #t=0 from existing object metadata (bar:#t=0 e.g.), This allows for reactive URI Template defined in object metadata elsewhere (src:://m.com/cat.mp4#{foo} e.g., to play media using media fragment URI). NOTE: metadata-key should not start with # + + +ANIMATION +#<tag_or_objectname>=<animationname> +string=string +#people=walk #people=noanim +assign a different animation to object(s) + @@ -546,13 +554,14 @@ That way, if the link gets shared, the XR Fragments implementation at http -media parameter (shader uniform) -u:= -float -vec2 + + ++0.5,+0.5 +scroll instantly by adding 0.5 to the current uv coordinates +

| media parameter (shader uniform) | u:= | u:color=1,0,0 | set shader uniform value |

* = this is extending the W3C media fragments with (missing) playback/viewport-control. Normally #t=0,2 implies setting start/stop-values AND starting playback, whereas #s=0&loop allows pausing a video, speeding up/slowing down media, as well as enabling/disabling looping.

@@ -666,7 +675,7 @@ For example, to render a portal with a preview-version of the scene, create an 3
  • the Y-coordinate of pos identifies the floorposition. This means that desktop-projections usually need to add 1.5m (average person height) on top (which is done automatically by VR/AR headsets).
  • set the position of the camera accordingly to the vector3 values of #pos
  • rot sets the rotation of the camera (only for non-VR/AR headsets)
  • -
  • t sets the playbackspeed and animation-range of the current scene animation(s) or src-mediacontent (video/audioframes e.g., use t=0,7,7 to ‘STOP’ at frame 7 e.g.)
  • +
  • t in the top-URL sets the playbackspeed and animation-range of the global scene animation
  • after scene load: in case an href does not mention any pos-coordinate, pos=0,0,0 will be assumed
  • @@ -825,6 +834,8 @@ Resizing will be happen accordingly to its placeholder object aquariumcube
  • ignore previous rule in special cases, like clicking an href using camera-portal collision (the back-button would cause a teleport-loop)

  • href-events should bubble upward the node-tree

  • + +
  • the end-user navigator back/forward buttons should repeat a back/forward action until a pos=... primitive is found (the inbetween interaction URI’s are only for UX research purposes)

  • » example implementation
    diff --git a/doc/RFC_XR_Fragments.md b/doc/RFC_XR_Fragments.md index cf15481..c435bf8 100644 --- a/doc/RFC_XR_Fragments.md +++ b/doc/RFC_XR_Fragments.md @@ -278,6 +278,8 @@ These are automatic fragment-to-metadata mappings, which only trigger if the 3D | | | +0.5,+0.5 | scroll instantly by adding 0.5 to the current uv coordinates | | | | 0.2,1,0.1,0.1 | scroll (lerp) to uv coordinate `0,2,1` with `0.1` units per second | | | | 0,0,0,+0.1 | scroll v coordinates with `0.1` units per second (infinitely) | +| | | +0.5,+0.5 | scroll instantly by adding 0.5 to the current uv coordinates | + | media parameter (shader uniform) | u:= | u:color=1,0,0 | set shader uniform value | > \* = this is extending the [W3C media fragments](https://www.w3.org/TR/media-frags/#mf-advanced) with (missing) playback/viewport-control. Normally `#t=0,2` implies setting start/stop-values AND starting playback, whereas `#s=0&loop` allows pausing a video, speeding up/slowing down media, as well as enabling/disabling looping. diff --git a/doc/RFC_XR_Fragments.txt b/doc/RFC_XR_Fragments.txt index 3c08de3..0f894af 100644 --- a/doc/RFC_XR_Fragments.txt +++ b/doc/RFC_XR_Fragments.txt @@ -3,7 +3,7 @@ Jens & Leon Internet Engineering Task Force L.R. van Kammen -Internet-Draft 9 February 2024 +Internet-Draft 16 February 2024 Intended status: Informational @@ -43,7 +43,7 @@ Status of This Memo time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress." - This Internet-Draft will expire on 12 August 2024. + This Internet-Draft will expire on 19 August 2024. Copyright Notice @@ -53,7 +53,7 @@ Copyright Notice -van Kammen Expires 12 August 2024 [Page 1] +van Kammen Expires 19 August 2024 [Page 1] Internet-Draft XR Fragments February 2024 @@ -77,22 +77,22 @@ Table of Contents 4.1. List of metadata for 3D nodes . . . . . . . . . . . . . . 8 4.2. Fragment-to-metadata mapping . . . . . . . . . . . . . . 8 4.3. media fragments and datatypes . . . . . . . . . . . . . . 10 - 5. Spatial Referencing 3D . . . . . . . . . . . . . . . . . . . 12 + 5. Spatial Referencing 3D . . . . . . . . . . . . . . . . . . . 13 6. Navigating 3D . . . . . . . . . . . . . . . . . . . . . . . . 13 7. Top-level URL processing . . . . . . . . . . . . . . . . . . 14 8. Embedding XR content using src . . . . . . . . . . . . . . . 15 9. Navigating content href portals . . . . . . . . . . . . . . . 17 - 9.1. Walking surfaces . . . . . . . . . . . . . . . . . . . . 18 - 9.2. UX spec . . . . . . . . . . . . . . . . . . . . . . . . . 18 + 9.1. Walking surfaces . . . . . . . . . . . . . . . . . . . . 19 + 9.2. UX spec . . . . . . . . . . . . . . . . . . . . . . . . . 19 9.3. Scaling instanced content . . . . . . . . . . . . . . . . 19 - 10. XR Fragment: pos . . . . . . . . . . . . . . . . . . . . . . 19 - 11. XR Fragment: rot . . . . . . . . . . . . . . . . . . . . . . 19 - 12. XR Fragment: t . . . . . . . . . . . . . . . . . . . . . . . 19 - 13. XR audio/video integration . . . . . . . . . . . . . . . . . 20 - 14. XR Fragment filters . . . . . . . . . . . . . . . . . . . . . 20 - 14.1. including/excluding . . . . . . . . . . . . . . . . . . 21 + 10. XR Fragment: pos . . . . . . . . . . . . . . . . . . . . . . 20 + 11. XR Fragment: rot . . . . . . . . . . . . . . . . . . . . . . 20 + 12. XR Fragment: t . . . . . . . . . . . . . . . . . . . . . . . 20 + 13. XR audio/video integration . . . . . . . . . . . . . . . . . 21 + 14. XR Fragment filters . . . . . . . . . . . . . . . . . . . . . 21 + 14.1. including/excluding . . . . . . . . . . . . . . . . . . 22 14.2. Filter Parser . . . . . . . . . . . . . . . . . . . . . 22 - 15. Visible links . . . . . . . . . . . . . . . . . . . . . . . . 22 + 15. Visible links . . . . . . . . . . . . . . . . . . . . . . . . 23 16. Text in XR (tagging,linking to spatial objects) . . . . . . . 23 16.1. Default Data URI mimetype . . . . . . . . . . . . . . . 27 16.2. URL and Data URI . . . . . . . . . . . . . . . . . . . . 28 @@ -101,7 +101,7 @@ Table of Contents 18. Topic-based index-less Webrings . . . . . . . . . . . . . . . 32 19. URI Templates (RFC6570) . . . . . . . . . . . . . . . . . . . 33 20. Security Considerations . . . . . . . . . . . . . . . . . . . 33 - 21. FAQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 + 21. FAQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 22. authors . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 23. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 34 24. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 34 @@ -109,7 +109,7 @@ Table of Contents -van Kammen Expires 12 August 2024 [Page 2] +van Kammen Expires 19 August 2024 [Page 2] Internet-Draft XR Fragments February 2024 @@ -165,7 +165,7 @@ Internet-Draft XR Fragments February 2024 -van Kammen Expires 12 August 2024 [Page 3] +van Kammen Expires 19 August 2024 [Page 3] Internet-Draft XR Fragments February 2024 @@ -221,7 +221,7 @@ Internet-Draft XR Fragments February 2024 -van Kammen Expires 12 August 2024 [Page 4] +van Kammen Expires 19 August 2024 [Page 4] Internet-Draft XR Fragments February 2024 @@ -277,7 +277,7 @@ Internet-Draft XR Fragments February 2024 -van Kammen Expires 12 August 2024 [Page 5] +van Kammen Expires 19 August 2024 [Page 5] Internet-Draft XR Fragments February 2024 @@ -333,7 +333,7 @@ Internet-Draft XR Fragments February 2024 -van Kammen Expires 12 August 2024 [Page 6] +van Kammen Expires 19 August 2024 [Page 6] Internet-Draft XR Fragments February 2024 @@ -376,24 +376,25 @@ Internet-Draft XR Fragments February 2024 | | | |xyz-coord | | | | |0.5,0,0 | +-----------------------+--------------------------------------+------------+------------+ - |W3C Media Fragments |media fragment |#t=0,2 #xywh|play/loop 3D| - |(https://www.w3.org/TR/|(#media%20fragments%20and%20datatypes)| |animation | - |media-frags/) | | |from 0 | + |W3C Media Fragments |media fragment |#t=0,2&loop |play (and | + |(https://www.w3.org/TR/|(#media%20fragments%20and%20datatypes)| |loop) 3D | + |media-frags/) | | |animation | + | | | |from 0 | | | | |seconds till| | | | |2 seconds | +-----------------------+--------------------------------------+------------+------------+ | | | |but can also| | | | |crop, | | | | |animate & | - | | | |configure | -van Kammen Expires 12 August 2024 [Page 7] +van Kammen Expires 19 August 2024 [Page 7] Internet-Draft XR Fragments February 2024 + | | | |configure | | | | |uv- | | | | |coordinates/| | | | |shader | @@ -441,15 +442,15 @@ Internet-Draft XR Fragments February 2024 | | | | |works when metadata-key| | | | | |starts with # | +----------------+--------------------------------------+-------------+---------------------+-----------------------+ - |*FOCUS* |# |string |#person |(and show) object(s) | -van Kammen Expires 12 August 2024 [Page 8] +van Kammen Expires 19 August 2024 [Page 8] Internet-Draft XR Fragments February 2024 + |*FOCUS* |# |string |#person |(and show) object(s) | | | | | |with tag: person or | | | | | |name person (XRWG | | | | | |lookup) | @@ -500,12 +501,15 @@ Internet-Draft XR Fragments February 2024 - -van Kammen Expires 12 August 2024 [Page 9] +van Kammen Expires 19 August 2024 [Page 9] Internet-Draft XR Fragments February 2024 + |*ANIMATION* |#= |string=string|#people=walk |assign a different | + | | | |#people=noanim |animation to object(s) | + +----------------+--------------------------------------+-------------+---------------------+-----------------------+ + Table 5 4.3. media fragments and datatypes @@ -514,79 +518,105 @@ Internet-Draft XR Fragments February 2024 | the 3D scene(file) *but also* media defined in src-metadata like | audio/video-files (mp3/mp4 e.g.) - +=========+=======================+===============+================+ - |type | syntax | example | info | - +=========+=======================+===============+================+ - |vector2 | x,y | 2,3.0 | 2-dimensional | - | | | | vector | - +---------+-----------------------+---------------+----------------+ - |vector3 | x,y,z | 2,3.0,4 | 3-dimensional | - | | | | vector | - +---------+-----------------------+---------------+----------------+ - |temporal | t=x | 0 | play from 0 | - |W3C media| | | seconds to end | - |fragment | | | (and stop) | - +---------+-----------------------+---------------+----------------+ - |temporal | t=x,y | 0,2 | play from 0 | - |W3C media| | | seconds till 2 | - |fragment | | | seconds (and | - | | | | stop) | - +---------+-----------------------+---------------+----------------+ - |temporal | s=x | 1 | set playback | - |W3C media| | | speed of | - |fragment | | | audio/video/3D | - |* | | | anim | - +---------+-----------------------+---------------+----------------+ - |temporal | [-]loop | loop | enable looped | - |W3C media| | | playback of | - |fragment | | | audio/video/3D | - |* | | | anim | - +---------+-----------------------+---------------+----------------+ - | | | -loop | disable looped | - | | | | playback (does | - | | | | not affect | - | | | | playbackstate | - | | | | of media) | - +---------+-----------------------+---------------+----------------+ - |vector2 | uv=uv,v,uspeed,vspeed | 0,0 | set uv offset | - | | | | instantly | - | | | | (default speed | - | | | | = 1,1) | - +---------+-----------------------+---------------+----------------+ - | | | +0.5,+0.5 | scroll | + +==========+=======================+===============+================+ + | type | syntax | example | info | + +==========+=======================+===============+================+ + | vector2 | x,y | 2,3.0 | 2-dimensional | + | | | | vector | + +----------+-----------------------+---------------+----------------+ + | vector3 | x,y,z | 2,3.0,4 | 3-dimensional | + | | | | vector | + +----------+-----------------------+---------------+----------------+ + | temporal | t=x | 0 | play from 0 | + | W3C | | | seconds to | + | media | | | end (and | + | fragment | | | stop) | + +----------+-----------------------+---------------+----------------+ + | temporal | t=x,y | 0,2 | play from 0 | + | W3C | | | seconds till | + | media | | | 2 seconds | + | fragment | | | (and stop) | + +----------+-----------------------+---------------+----------------+ + | temporal | s=x | 1 | set playback | + | W3C | | | speed of | + | media | | | audio/ | + | fragment | | | video/3D anim | + | * | | | | + +----------+-----------------------+---------------+----------------+ + | temporal | [-]loop | loop | enable looped | + | W3C | | | playback of | + | media | | | audio/ | + | fragment | | | video/3D anim | + | * | | | | + +----------+-----------------------+---------------+----------------+ + | | | -loop | disable | + | | | | looped | + | | | | playback | + | | | | (does not | + | | | | affect | -van Kammen Expires 12 August 2024 [Page 10] +van Kammen Expires 19 August 2024 [Page 10] Internet-Draft XR Fragments February 2024 - | | | | instantly by | - | | | | adding 0.5 to | - | | | | the current uv | - | | | | coordinates | - +---------+-----------------------+---------------+----------------+ - | | | 0.2,1,0.1,0.1 | scroll (lerp) | - | | | | to uv | - | | | | coordinate | - | | | | 0,2,1 with 0.1 | - | | | | units per | - | | | | second | - +---------+-----------------------+---------------+----------------+ - | | | 0,0,0,+0.1 | scroll v | - | | | | coordinates | - | | | | with 0.1 units | - | | | | per second | - | | | | (infinitely) | - +---------+-----------------------+---------------+----------------+ - |media | u:== | u:color=1,0,0 | set + shader uniform value | + + + + + + + + + +van Kammen Expires 19 August 2024 [Page 11] + +Internet-Draft XR Fragments February 2024 - Table 6 | * = this is extending the W3C media fragments | (https://www.w3.org/TR/media-frags/#mf-advanced) with (missing) @@ -609,15 +639,6 @@ Internet-Draft XR Fragments February 2024 * https://shaders.org/plasma.glsl#t=0&u:col1=1,0,0&u:col2=0,1,0 (red-green shader plasma starts playing from time-offset 0) - - - - -van Kammen Expires 12 August 2024 [Page 11] - -Internet-Draft XR Fragments February 2024 - - +──────────────────────────────────────────────────────────+ │ │ │ index.gltf#playall │ @@ -644,6 +665,15 @@ Internet-Draft XR Fragments February 2024 > NOTE: URI Template variables are immutable and respect scope: in other words, the end-user cannot modify `blue` by entering an URL like `#blue=.....` in the browser URL, and `blue` is not accessible by the plane/media-object (however `{play}` would work). + + + + +van Kammen Expires 19 August 2024 [Page 12] + +Internet-Draft XR Fragments February 2024 + + 5. Spatial Referencing 3D XR Fragments assume the following objectname-to-URIFragment mapping: @@ -666,14 +696,6 @@ Internet-Draft XR Fragments February 2024 | Every 3D fileformat supports named 3D object, and this name allows | URLs (fragments) to reference them (and their children objects). - - - -van Kammen Expires 12 August 2024 [Page 12] - -Internet-Draft XR Fragments February 2024 - - Clever nested design of 3D scenes allow great ways for re-using content, and/or previewing scenes. For example, to render a portal with a preview-version of the scene, @@ -701,12 +723,19 @@ Internet-Draft XR Fragments February 2024 | #rot=0,90,0 | vector3 | rotate camera | +--------------------+---------+-----------------------------+ + + +van Kammen Expires 19 August 2024 [Page 13] + +Internet-Draft XR Fragments February 2024 + + Table 7 - » example implementation + » example implementation (https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/ three/xrf/pos.js) - » discussion (https://github.com/coderofsalvation/xrfragment/ + » discussion (https://github.com/coderofsalvation/xrfragment/ issues/5) 1. the Y-coordinate of pos identifies the floorposition. This means @@ -715,23 +744,13 @@ Internet-Draft XR Fragments February 2024 2. set the position of the camera accordingly to the vector3 values of #pos 3. rot sets the rotation of the camera (only for non-VR/AR headsets) - 4. t sets the playbackspeed and animation-range of the current scene - animation(s) or src-mediacontent (video/audioframes e.g., use - t=0,7,7 to 'STOP' at frame 7 e.g.) + 4. t in the top-URL sets the playbackspeed and animation-range of + the global scene animation 5. after scene load: in case an href does not mention any pos- coordinate, pos=0,0,0 will be assumed - - - - -van Kammen Expires 12 August 2024 [Page 13] - -Internet-Draft XR Fragments February 2024 - - Here's an ascii representation of a 3D scene-graph which contains 3D - objects ◻ and their metadata: + objects ◻ and their metadata: +────────────────────────────────────────────────────────+ │ │ @@ -758,6 +777,15 @@ Internet-Draft XR Fragments February 2024 The URL-processing-flow for hypermedia browsers goes like this: + + + + +van Kammen Expires 19 August 2024 [Page 14] + +Internet-Draft XR Fragments February 2024 + + 1. IF a #cube matches a custom property-key (of an object) in the 3D file/scene (#cube: #......) THEN execute that predefined_view. @@ -774,18 +802,6 @@ Internet-Draft XR Fragments February 2024 5. IF a #cube matches anything else in the XR Word Graph (XRWG) draw wires to them (text or related objects). - - - - - - - -van Kammen Expires 12 August 2024 [Page 14] - -Internet-Draft XR Fragments February 2024 - - 8. Embedding XR content using src src is the 3D version of the based on the scale-property (of a geometry-less placeholder, an 'empty'-object in blender e.g.). For more info see Chapter Scaling. + + + + +van Kammen Expires 19 August 2024 [Page 16] + +Internet-Draft XR Fragments February 2024 + + 6. external src values should be served with appropriate mimetype (so the XR Fragment-compatible browser will now how to render it). The bare minimum supported mimetypes are: @@ -888,16 +919,6 @@ Internet-Draft XR Fragments February 2024 position to 0,0,0 13. when the enduser clicks an href with #t=1,0,0 (play) will be applied to all src mediacontent with a timeline (mp4/mp3 e.g.) - - - - - -van Kammen Expires 12 August 2024 [Page 16] - -Internet-Draft XR Fragments February 2024 - - 14. a non-euclidian portal can be rendered for flat 3D objects (using stencil buffer e.g.) in case ofspatial src-values (an object #world3 or URL world3.fbx e.g.). @@ -908,19 +929,31 @@ Internet-Draft XR Fragments February 2024 * image/jpg * text/plain;charset=utf-8 - » example implementation + » example implementation (https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/ three/xrf/src.js) - » example 3D asset + » example 3D asset (https://github.com/coderofsalvation/xrfragment/blob/main/example/ assets/src.gltf#L192) - » discussion (https://github.com/coderofsalvation/xrfragment/ + » discussion (https://github.com/coderofsalvation/xrfragment/ issues/4) 9. Navigating content href portals navigation, portals & mutations + + + + + + + +van Kammen Expires 19 August 2024 [Page 17] + +Internet-Draft XR Fragments February 2024 + + +==========+==================+============================+ | fragment | type | example value | +==========+==================+============================+ @@ -947,13 +980,6 @@ Internet-Draft XR Fragments February 2024 (https://github.com/coderofsalvation/xrfragment/blob/dev/src/3rd/ js/three/navigator.js) for an example navigator). - - -van Kammen Expires 12 August 2024 [Page 17] - -Internet-Draft XR Fragments February 2024 - - 5. In XR mode, the navigator back/forward-buttons should be always visible (using a wearable e.g., see [here (https://github.com/coderofsalvation/xrfragment/blob/dev/example/ @@ -971,13 +997,26 @@ Internet-Draft XR Fragments February 2024 8. href-events should bubble upward the node-tree - » example implementation + 9. the end-user navigator back/forward buttons should repeat a back/ + forward action until a pos=... primitive is found (the inbetween + interaction URI's are only for UX research purposes) + + + + + +van Kammen Expires 19 August 2024 [Page 18] + +Internet-Draft XR Fragments February 2024 + + + » example implementation (https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/ three/xrf/href.js) - » example 3D asset + » example 3D asset (https://github.com/coderofsalvation/xrfragment/blob/main/example/ assets/href.gltf#L192) - » discussion (https://github.com/coderofsalvation/xrfragment/ + » discussion (https://github.com/coderofsalvation/xrfragment/ issues/1) 9.1. Walking surfaces @@ -1001,15 +1040,6 @@ Internet-Draft XR Fragments February 2024 another scene/file (and coordinate e.g. in case the URL contains XR Fragments). - - - - -van Kammen Expires 12 August 2024 [Page 18] - -Internet-Draft XR Fragments February 2024 - - 9.3. Scaling instanced content Sometimes embedded properties (like src) instance new objects. @@ -1028,6 +1058,14 @@ Internet-Draft XR Fragments February 2024 (maxsize=1.4 e.g.) * hide the ''placeholder'' object (material e.g.) * instance the src scene as a child of the existing object + + + +van Kammen Expires 19 August 2024 [Page 19] + +Internet-Draft XR Fragments February 2024 + + * calculate the bounding box of the instanced scene, and scale it accordingly (to 1.4 e.g.) @@ -1056,16 +1094,6 @@ Internet-Draft XR Fragments February 2024 * playposition is reset to framestart, when framestart or framestop is greater than 0 | - - - - - -van Kammen Expires 12 August 2024 [Page 19] - -Internet-Draft XR Fragments February 2024 - - | Example Value | Explanation | |-|-| | 1,1,100 | play loop between frame 1 and 100 | | 1,1,0 | play once from frame 1 (oneshot) | | 1,0,0 | play (previously set looprange if any) | | 0,0,0 | pause | | @@ -1083,6 +1111,17 @@ Internet-Draft XR Fragments February 2024 issues/10] (https://github.com/coderofsalvation/xrfragment/ issues/10])] + + + + + + +van Kammen Expires 19 August 2024 [Page 20] + +Internet-Draft XR Fragments February 2024 + + 13. XR audio/video integration To play global audio/video items: @@ -1105,23 +1144,6 @@ Internet-Draft XR Fragments February 2024 Include, exclude, hide/shows objects using space-separated strings: - - - - - - - - - - - - -van Kammen Expires 12 August 2024 [Page 20] - -Internet-Draft XR Fragments February 2024 - - +====================+===========================================+ | example | outcome | +====================+===========================================+ @@ -1147,6 +1169,15 @@ Internet-Draft XR Fragments February 2024 which used a dedicated q= variable (now deprecated and usable directly) + + + + +van Kammen Expires 19 August 2024 [Page 21] + +Internet-Draft XR Fragments February 2024 + + 14.1. including/excluding By default, selectors work like photoshop-layers: they scan for @@ -1171,13 +1202,6 @@ Internet-Draft XR Fragments February 2024 Table 11 - - -van Kammen Expires 12 August 2024 [Page 21] - -Internet-Draft XR Fragments February 2024 - - | NOTE 1: after an external embedded object has been instanced (src: | https://y.com/bar.fbx#room e.g.), filters do not affect them | anymore (reason: local tag/name collisions can be mitigated @@ -1188,11 +1212,11 @@ Internet-Draft XR Fragments February 2024 | colorbuffer (to allow children being still visible while their | parents are invisible). - » example implementation + » example implementation (https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/ - three/xrf/q.js) » example 3D asset + three/xrf/q.js) » example 3D asset (https://github.com/coderofsalvation/xrfragment/blob/main/example/ - assets/filter.gltf#L192) » discussion + assets/filter.gltf#L192) » discussion (https://github.com/coderofsalvation/xrfragment/issues/3) 14.2. Filter Parser @@ -1201,6 +1225,15 @@ Internet-Draft XR Fragments February 2024 1. create an associative array/object to store filter-arguments as objects + + + + +van Kammen Expires 19 August 2024 [Page 22] + +Internet-Draft XR Fragments February 2024 + + 2. detect object id's & properties foo=1 and foo (reference regex= ~/^.*=[><=]?/ ) 3. detect excluders like -foo,-foo=1,-.foo,-/foo (reference regex= @@ -1226,14 +1259,6 @@ Internet-Draft XR Fragments February 2024 #mytag e.g.) are triggered by the enduser (via toplevel URL or clicking href): - - - -van Kammen Expires 12 August 2024 [Page 22] - -Internet-Draft XR Fragments February 2024 - - 1. draw a wire from the enduser (preferabbly a bit below the camera, heartposition) to object(s) matching that ID (objectname) 2. draw a wire from the enduser (preferabbly a bit below the camera, @@ -1257,6 +1282,14 @@ Internet-Draft XR Fragments February 2024 How does XR Fragments interlink text with objects? + + + +van Kammen Expires 19 August 2024 [Page 23] + +Internet-Draft XR Fragments February 2024 + + | The XR Fragments does this by collapsing space into a *Word Graph* | (the *XRWG* example | (https://github.com/coderofsalvation/xrfragment/blob/feat/macros/ @@ -1282,14 +1315,6 @@ Internet-Draft XR Fragments February 2024 1. XR Fragments promotes (de)serializing a scene to the XRWG (example (https://github.com/coderofsalvation/xrfragment/blob/fe at/macros/src/3rd/js/XRWG.js)) - - - -van Kammen Expires 12 August 2024 [Page 23] - -Internet-Draft XR Fragments February 2024 - - 2. XR Fragments primes the XRWG, by collecting words from the tag and name-property of 3D objects. 3. XR Fragments primes the XRWG, by collecting words from @@ -1314,6 +1339,13 @@ Internet-Draft XR Fragments February 2024 scroll-to-text-fragment (https://github.com/WICG/scroll-to-text- fragment) will be considered) + + +van Kammen Expires 19 August 2024 [Page 24] + +Internet-Draft XR Fragments February 2024 + + Example: http://y.io/z.fbx | Derived XRWG (expressed as BibTex) @@ -1338,14 +1370,6 @@ Internet-Draft XR Fragments February 2024 | the #john@baroque-bib associates both text John and objectname | john, with tag baroque - - - -van Kammen Expires 12 August 2024 [Page 24] - -Internet-Draft XR Fragments February 2024 - - Another example: http://y.io/z.fbx | Derived XRWG (expressed as BibTex) @@ -1371,6 +1395,13 @@ Internet-Draft XR Fragments February 2024 | same XRWG, however on top of that 2 tages (house and todo) are now | associated with text/objectname/tag 'baroque'. + + +van Kammen Expires 19 August 2024 [Page 25] + +Internet-Draft XR Fragments February 2024 + + As seen above, the XRWG can expand bibs (https://github.com/coderofsalvation/hashtagbibs) (and the whole scene) to BibTeX. @@ -1392,16 +1423,6 @@ Internet-Draft XR Fragments February 2024 Table 12 - - - - - -van Kammen Expires 12 August 2024 [Page 25] - -Internet-Draft XR Fragments February 2024 - - | hashtagbibs (https://github.com/coderofsalvation/hashtagbibs) | potentially allow the enduser to annotate text/objects by | *speaking/typing/scanning associations*, which the XR Browser @@ -1429,6 +1450,14 @@ Internet-Draft XR Fragments February 2024 (contextmenu e.g.) of any XR text, anywhere anytime. 11. respect multi-line BiBTeX metadata in text because of the core principle (#core-principle) + + + +van Kammen Expires 19 August 2024 [Page 26] + +Internet-Draft XR Fragments February 2024 + + 12. Default font (unless specified otherwise) is a modern monospace font, for maximized tabular expressiveness (see the core principle (#core-principle)). @@ -1445,19 +1474,6 @@ Internet-Draft XR Fragments February 2024 Fictional chat: - - - - - - - - -van Kammen Expires 12 August 2024 [Page 26] - -Internet-Draft XR Fragments February 2024 - - Hey what about this: https://my.com/station.gltf#pos=0,0,1&rot=90,2,0&t=500,1000 I'm checking it right now I don't see everything..where's our text from yesterday? @@ -1490,6 +1506,14 @@ Internet-Draft XR Fragments February 2024 This indicates that: * utf-8 is supported by default + + + +van Kammen Expires 19 August 2024 [Page 27] + +Internet-Draft XR Fragments February 2024 + + * lines beginning with @ will not be rendered verbatim by default (read more (https://github.com/coderofsalvation/ hashtagbibs#hashtagbib-mimetypes)) @@ -1506,14 +1530,6 @@ Internet-Draft XR Fragments February 2024 Advantages: - - - -van Kammen Expires 12 August 2024 [Page 27] - -Internet-Draft XR Fragments February 2024 - - * auto-expanding of hashtagbibs (https://github.com/coderofsalvation/hashtagbibs) associations * out-of-the-box (de)multiplex human text and metadata in one go @@ -1537,6 +1553,23 @@ Internet-Draft XR Fragments February 2024 16.2. URL and Data URI + + + + + + + + + + + + +van Kammen Expires 19 August 2024 [Page 28] + +Internet-Draft XR Fragments February 2024 + + +--------------------------------------------------------------+ +------------------------+ | | | author.com/article.txt | | index.gltf | +------------------------+ @@ -1563,13 +1596,6 @@ Internet-Draft XR Fragments February 2024 | object note_canvas with 'todo', the enduser can type or speak | #note_canvas@todo - - -van Kammen Expires 12 August 2024 [Page 28] - -Internet-Draft XR Fragments February 2024 - - 16.3. XR Text example parser To prime the XRWG with text from plain text src-values, here's an @@ -1592,6 +1618,14 @@ xrtext = { }, decode: (str) => { + + + +van Kammen Expires 19 August 2024 [Page 29] + +Internet-Draft XR Fragments February 2024 + + // bibtex: ↓@ ↓ ↓property ↓end let pat = [ /@/, /^\S+[,{}]/, /},/, /}/ ] let tags = [], text='', i=0, prop='' @@ -1619,13 +1653,6 @@ xrtext = { return {text, tags} }, - - -van Kammen Expires 12 August 2024 [Page 29] - -Internet-Draft XR Fragments February 2024 - - encode: (text,tags) => { let str = text+"\n" for( let i in tags ){ @@ -1648,6 +1675,13 @@ Internet-Draft XR Fragments February 2024 | above can be used as a startingpoint for LLVM's to translate/ | steelman to a more formal form/language. + + +van Kammen Expires 19 August 2024 [Page 30] + +Internet-Draft XR Fragments February 2024 + + str = ` hello world here are some hashtagbibs followed by bibtex: @@ -1668,20 +1702,6 @@ console.log( xrtext.encode(text,tags) ) // multiplex text & bibtex back to This expands to the following (hidden by default) BibTex appendix: - - - - - - - - - -van Kammen Expires 12 August 2024 [Page 30] - -Internet-Draft XR Fragments February 2024 - - hello world here are some hashtagbibs followed by bibtex: @@ -1709,6 +1729,15 @@ Internet-Draft XR Fragments February 2024 1. defining a different transport protocol (https vs ipfs or DAT) in src or href values can make a difference + + + + +van Kammen Expires 19 August 2024 [Page 31] + +Internet-Draft XR Fragments February 2024 + + 2. mirroring files on another protocol using (HTTP) errorcode tags in src or href properties 3. in case of src: nesting a copy of the embedded object in the @@ -1721,23 +1750,6 @@ Internet-Draft XR Fragments February 2024 For example: - - - - - - - - - - - - -van Kammen Expires 12 August 2024 [Page 31] - -Internet-Draft XR Fragments February 2024 - - +────────────────────────────────────────────────────────+ │ │ │ index.gltf │ @@ -1774,6 +1786,14 @@ Internet-Draft XR Fragments February 2024 * href: schoolA.edu/projects.gltf#math&-topics math * href: schoolB.edu/projects.gltf#math&-courses math + + + +van Kammen Expires 19 August 2024 [Page 32] + +Internet-Draft XR Fragments February 2024 + + * href: university.edu/projects.gltf#math&-theme math | This would hide all object tagged with topic, courses or theme @@ -1784,16 +1804,6 @@ Internet-Draft XR Fragments February 2024 separate content into separate files, or show/hide things using a complex logiclayer like javascript. - - - - - -van Kammen Expires 12 August 2024 [Page 32] - -Internet-Draft XR Fragments February 2024 - - 19. URI Templates (RFC6570) XR Fragments adopts Level1 URI *Fragment* expansion to provide safe @@ -1828,6 +1838,18 @@ Internet-Draft XR Fragments February 2024 In fact, it is much safer than relying on a scripting language (javascript) which can change URN too. + + + + + + + +van Kammen Expires 19 August 2024 [Page 33] + +Internet-Draft XR Fragments February 2024 + + 21. FAQ *Q:* Why is everything HTTP GET-based, what about POST/PUT/DELETE @@ -1842,14 +1864,6 @@ Internet-Draft XR Fragments February 2024 scope as it unhyperifies hypermedia, and this is up to XR hypermedia browser-extensions. Historically scripting/Javascript seems to been able to turn webpages - - - -van Kammen Expires 12 August 2024 [Page 33] - -Internet-Draft XR Fragments February 2024 - - from hypermedia documents into its opposite (hyperscripted nonhypermedia documents). In order to prevent this backward-movement (hypermedia tends to @@ -1872,7 +1886,7 @@ Internet-Draft XR Fragments February 2024 22. authors * Leon van Kammen (@lvk@mastodon.online) - * Jens Finkhäuser (@jens@social.finkhaeuser.de) + * Jens Finkhäuser (@jens@social.finkhaeuser.de) 23. IANA Considerations @@ -1884,28 +1898,23 @@ Internet-Draft XR Fragments February 2024 * Future of Text (https://futureoftext.org) * visual-meta.info (https://visual-meta.info) * Michiel Leenaars + + + +van Kammen Expires 19 August 2024 [Page 34] + +Internet-Draft XR Fragments February 2024 + + * Gerben van der Broeke * Mauve - * Jens Finkhäuser + * Jens Finkhäuser * Marc Belmont * Tim Gerritsen * Frode Hegland * Brandel Zackernuk * Mark Anderson - - - - - - - - -van Kammen Expires 12 August 2024 [Page 34] - -Internet-Draft XR Fragments February 2024 - - 25. Appendix: Definitions +=================+=============================================+ @@ -1945,6 +1954,14 @@ Internet-Draft XR Fragments February 2024 | spacetime | positions camera, triggers scene-preset/ | | hashtags | time | +-----------------+---------------------------------------------+ + + + +van Kammen Expires 19 August 2024 [Page 35] + +Internet-Draft XR Fragments February 2024 + + | teleportation | repositioning the enduser to a different | | | position (or 3D scene/file) | +-----------------+---------------------------------------------+ @@ -1954,14 +1971,6 @@ Internet-Draft XR Fragments February 2024 | placeholder | a 3D object which with src-metadata (which | | object | will be replaced by the src-data.) | +-----------------+---------------------------------------------+ - - - -van Kammen Expires 12 August 2024 [Page 35] - -Internet-Draft XR Fragments February 2024 - - | src | (HTML-piggybacked) metadata of a 3D object | | | which instances content | +-----------------+---------------------------------------------+ @@ -1991,7 +2000,7 @@ Internet-Draft XR Fragments February 2024 | extrospective | outward sensemaking ("I'm fairly sure John | | | is a person who lives in oklahoma") | +-----------------+---------------------------------------------+ - | ◻ | ascii representation of an 3D object/mesh | + | ◻ | ascii representation of an 3D object/mesh | +-----------------+---------------------------------------------+ | (un)obtrusive | obtrusive: wrapping human text/thought in | | | XML/HTML/JSON obfuscates human text into a | @@ -2001,6 +2010,14 @@ Internet-Draft XR Fragments February 2024 | | plane | +-----------------+---------------------------------------------+ | BibTeX | simple tagging/citing/referencing standard | + + + +van Kammen Expires 19 August 2024 [Page 36] + +Internet-Draft XR Fragments February 2024 + + | | for plaintext | +-----------------+---------------------------------------------+ | BibTag | a BibTeX tag | @@ -2011,13 +2028,6 @@ Internet-Draft XR Fragments February 2024 | | XML | +-----------------+---------------------------------------------+ - - -van Kammen Expires 12 August 2024 [Page 36] - -Internet-Draft XR Fragments February 2024 - - Table 13 @@ -2059,14 +2069,4 @@ Internet-Draft XR Fragments February 2024 - - - - - - - - - - -van Kammen Expires 12 August 2024 [Page 37] +van Kammen Expires 19 August 2024 [Page 37] diff --git a/doc/RFC_XR_Fragments.xml b/doc/RFC_XR_Fragments.xml index e65b895..80523af 100644 --- a/doc/RFC_XR_Fragments.xml +++ b/doc/RFC_XR_Fragments.xml @@ -48,18 +48,18 @@ XR Fragments exploits the fact that all 3D models already contain such metadata: Instead of forcing authors to combine 3D/2D objects programmatically (publishing thru a game-editor e.g.), XR Fragments integrates all which allows a universal viewing experience.
    - +───────────────────────────────────────────────────────────────────────────────────────────────+ │ │ │ U R N │ │ U R L | │ │ | |-----------------+--------| │ │ +--------------------------------------------------| │ │ | │ - │ + https://foo.com/some/foo/scene.glb#someview <-- http URI (=URL and has URN) │ + │ + https://foo.com/some/foo/scene.glb#someview <-- http URI (=URL and has URN) │ │ | │ - │ + ipfs://cfe0987ec9r9098ecr/cats.fbx#someview <-- an IPFS URI (=URL and has URN) │ + │ + ipfs://cfe0987ec9r9098ecr/cats.fbx#someview <-- an IPFS URI (=URL and has URN) │ │ │ - │ ec09f7e9cf8e7f09c8e7f98e79c09ef89e000efece8f7ecfe9fe <-- an interpeer URI │ + │ ec09f7e9cf8e7f09c8e7f98e79c09ef89e000efece8f7ecfe9fe <-- an interpeer URI │ │ │ │ │ │ |------------------------+-------------------------| │ @@ -68,20 +68,19 @@ Instead of forcing authors to combine 3D/2D objects programmatically (publishing │ │ +───────────────────────────────────────────────────────────────────────────────────────────────+ -]]> Fact: our typical browser URL's are just a possible implementation of URI's (for untapped humancentric potential of URI's see interpeer.io)

    XR Fragments does not look at XR (or the web) thru the lens of HTML or URLs.
    But approaches things from a higherlevel feedbackloop/hypermedia browser-perspective.
    Below you can see how this translates back into good-old URLs: - +───────────────────────────────────────────────────────────────────────────────────────────────+ │ │ │ the soul of any URL: ://macro /meso ?micro #nano │ │ │ │ 2D URL: ://library.com /document ?search #chapter │ │ │ - │ 4D URL: ://park.com /4Dscene.fbx ─> ?other.glb ─> #view ───> hashbus │ + │ 4D URL: ://park.com /4Dscene.fbx ─> ?other.glb ─> #view ───> hashbus │ │ │ #filter │ │ │ │ #tag │ │ │ │ (hypermediatic) #material │ │ @@ -89,14 +88,13 @@ But approaches things from a higherlevel feedbackloop/hypermedia browser-perspec │ │ ( loop ) #texture │ │ │ │ #variable │ │ │ │ │ │ - │ XRWG <─────────────────────<─────────────+ │ + │ XRWG <─────────────────────<─────────────+ │ │ │ │ │ - │ └─ objects ──────────────>─────────────+ │ + │ └─ objects ──────────────>─────────────+ │ │ │ │ │ +───────────────────────────────────────────────────────────────────────────────────────────────+ -]]>
    ?-linked and #-linked navigation allows a Hypermediatic FeedbackLoop (HFL) between external and internal 4D navigation.
    Traditional webbrowsers can become 4D document-ready by: @@ -174,10 +172,9 @@ But approaches things from a higherlevel feedbackloop/hypermedia browser-perspec
    XR Fragment URL Grammar For typical HTTP-like browsers/applications: - +reserved = gen-delims / sub-delims +gen-delims = "#" / "&" +sub-delims = "," / "="
    Example: ://foo.com/my3d.gltf#pos=1,0,0&prio=-5&t=0,100
    @@ -237,8 +234,8 @@ That way, if the link gets shared, the XR Fragments implementation at https: - - + + @@ -358,6 +355,14 @@ That way, if the link gets shared, the XR Fragments implementation at https: + + + + + + + +
    W3C Media Fragments media fragment#t=0,2 #xywhplay/loop 3D animation from 0 seconds till 2 seconds#t=0,2&loopplay (and loop) 3D animation from 0 seconds till 2 seconds
    #foo=bar sets URI Template variable foo to the value #t=0 from existing object metadata (bar:#t=0 e.g.), This allows for reactive URI Template defined in object metadata elsewhere (src:://m.com/cat.mp4#{foo} e.g., to play media using media fragment URI). NOTE: metadata-key should not start with #
    ANIMATION#<tag_or_objectname>=<animationname>string=string#people=walk #people=noanimassign a different animation to object(s)
    @@ -452,13 +457,14 @@ That way, if the link gets shared, the XR Fragments implementation at https: -media parameter (shader uniform) -u:<uniform>=<string -float -vec2 + + ++0.5,+0.5 +scroll instantly by adding 0.5 to the current uv coordinates -
    * = this is extending the W3C media fragments with (missing) playback/viewport-control. Normally #t=0,2 implies setting start/stop-values AND starting playback, whereas #s=0&loop allows pausing a video, speeding up/slowing down media, as well as enabling/disabling looping. +| media parameter (shader uniform) | u:<uniform>=<string|float|vec2|vec3|vec4> | u:color=1,0,0 | set shader uniform value | +
    * = this is extending the W3C media fragments with (missing) playback/viewport-control. Normally #t=0,2 implies setting start/stop-values AND starting playback, whereas #s=0&loop allows pausing a video, speeding up/slowing down media, as well as enabling/disabling looping. The rationale for uv is that the xywh Media Fragment deals with rectangular media, which does not translate well to 3D models (which use triangular polygons, not rectangular) positioned by uv-coordinates.
    Example URI's: @@ -468,11 +474,11 @@ That way, if the link gets shared, the XR Fragments implementation at https:
  • https://shaders.org/plasma.glsl#t=0&u:col1=1,0,0&u:col2=0,1,0 (red-green shader plasma starts playing from time-offset 0)
  • - +──────────────────────────────────────────────────────────+ │ │ │ index.gltf#playall │ │ │ │ - │ ├ # : #t=0&shared=play │ apply default XR Fragment on load (`t` plays global 3D animation timeline) + │ ├ # : #t=0&shared=play │ apply default XR Fragment on load (`t` plays global 3D animation timeline) │ ├ play : #t=l:0,2 │ variable for [URI Templates (RFC6570)](https://www.rfc-editor.org/rfc/rfc6570) │ │ │ │ ├── ◻ plane (with material) │ @@ -482,19 +488,18 @@ That way, if the link gets shared, the XR Fragments implementation at https: │ │ └ src: foo.jpg#suv=l:0,0.1 │ infinite texturescroll `v` of uv·coordinates with 0.1/fps │ │ │ │ ├── ◻ media │ - │ │ └ src: cat.mp4#t=l:2,10&uv=0.5,0.5 │ loop cat.mp4 (or mp3/wav/jpg) between 2 and 10 seconds (uv's shifted with 0.5,0.5) + │ │ └ src: cat.mp4#t=l:2,10&uv=0.5,0.5 │ loop cat.mp4 (or mp3/wav/jpg) between 2 and 10 seconds (uv's shifted with 0.5,0.5) │ │ │ │ └── ◻ wall │ │ ├ href: #color=blue │ updates uniform values (IFS shader e.g.) - │ ├ blue: t=0&u:col=0,0,1 │ variable for [Level1 URI Templates (RFC6570)](https://www.rfc-editor.org/rfc/rfc6570) - │ └ src: ://a.com/art.glsl#{color}&{shared} │ .fs/.vs/.glsl/.wgsl etc shader [Level1 URI Template (RFC6570)](https://www.rfc-editor.org/rfc/rfc6570) + │ ├ blue: t=0&u:col=0,0,1 │ variable for [Level1 URI Templates (RFC6570)](https://www.rfc-editor.org/rfc/rfc6570) + │ └ src: ://a.com/art.glsl#{color}&{shared} │ .fs/.vs/.glsl/.wgsl etc shader [Level1 URI Template (RFC6570)](https://www.rfc-editor.org/rfc/rfc6570) │ │ │ │ +──────────────────────────────────────────────────────────+ -> NOTE: URI Template variables are immutable and respect scope: in other words, the end-user cannot modify `blue` by entering an URL like `#blue=.....` in the browser URL, and `blue` is not accessible by the plane/media-object (however `{play}` would work). +> NOTE: URI Template variables are immutable and respect scope: in other words, the end-user cannot modify `blue` by entering an URL like `#blue=.....` in the browser URL, and `blue` is not accessible by the plane/media-object (however `{play}` would work). -]]> @@ -502,7 +507,7 @@ That way, if the link gets shared, the XR Fragments implementation at https:
    Spatial Referencing 3D XR Fragments assume the following objectname-to-URIFragment mapping: - my.io/scene.fbx +─────────────────────────────+ │ sky │ src: http://my.io/scene.fbx#sky (includes building,mainobject,floor) @@ -518,7 +523,6 @@ That way, if the link gets shared, the XR Fragments implementation at https: │ +─────────────────────────+ │ +─────────────────────────────+ -]]>
    Every 3D fileformat supports named 3D object, and this name allows URLs (fragments) to reference them (and their children objects).
    Clever nested design of 3D scenes allow great ways for re-using content, and/or previewing scenes.
    @@ -564,24 +568,23 @@ For example, to render a portal with a preview-version of the scene, create an 3
  • the Y-coordinate of pos identifies the floorposition. This means that desktop-projections usually need to add 1.5m (average person height) on top (which is done automatically by VR/AR headsets).
  • set the position of the camera accordingly to the vector3 values of #pos
  • rot sets the rotation of the camera (only for non-VR/AR headsets)
  • -
  • t sets the playbackspeed and animation-range of the current scene animation(s) or src-mediacontent (video/audioframes e.g., use t=0,7,7 to 'STOP' at frame 7 e.g.)
  • +
  • t in the top-URL sets the playbackspeed and animation-range of the global scene animation
  • after scene load: in case an href does not mention any pos-coordinate, pos=0,0,0 will be assumed
  • Here's an ascii representation of a 3D scene-graph which contains 3D objects and their metadata: - +────────────────────────────────────────────────────────+ │ │ │ index.gltf │ │ │ │ │ ├── ◻ buttonA │ - │ │ └ href: #pos=1,0,1&t=100,200 │ + │ │ └ href: #pos=1,0,1&t=100,200 │ │ │ │ │ └── ◻ buttonB │ - │ └ href: other.fbx │ <── file─agnostic (can be .gltf .obj etc) + │ └ href: other.fbx │ <── file─agnostic (can be .gltf .obj etc) │ │ +────────────────────────────────────────────────────────+ -]]> An XR Fragment-compatible browser viewing this scene, allows the end-user to interact with the buttonA and buttonB.
    @@ -629,7 +632,7 @@ It instances content (in objects) in the current scene/asset.
    Here's an ascii representation of a 3D scene-graph with 3D objects which embeds remote & local 3D objects with/out using filters: - +────────────────────────────────────────────────────────+ +─────────────────────────+ │ │ │ │ │ index.gltf │ │ ocean.com/aquarium.fbx │ │ │ │ │ ├ room │ @@ -646,7 +649,6 @@ It instances content (in objects) in the current scene/asset.
    │ └ src: #canvas │ │ │ +────────────────────────────────────────────────────────+ -]]> An XR Fragment-compatible browser viewing this scene, lazy-loads and projects painting.png onto the (plane) object called canvas (which is copy-instanced in the bed and livingroom).
    @@ -728,6 +730,8 @@ Resizing will be happen accordingly to its placeholder object aquariumcube
  • href-events should bubble upward the node-tree
  • +
  • the end-user navigator back/forward buttons should repeat a back/forward action until a pos=... primitive is found (the inbetween interaction URI's are only for UX research purposes) +
  • » example implementation
    @@ -965,7 +969,7 @@ XR Fragments does this by detecting Bib(s)Tex, without introducing a new languag Example: - http://y.io/z.fbx | Derived XRWG (expressed as BibTex) ----------------------------------------------------------------------------+-------------------------------------- | @house{castle, +-[src: data:.....]----------------------+ +-[3D mesh]-+ | url = {https://y.io/z.fbx#castle} @@ -983,12 +987,11 @@ XR Fragments does this by detecting Bib(s)Tex, without introducing a new languag | /|\ | | | / \ | | +--------+ | -]]>
    the #john@baroque-bib associates both text John and objectname john, with tag baroque
    Another example: - http://y.io/z.fbx | Derived XRWG (expressed as BibTex) ----------------------------------------------------------------------------+-------------------------------------- | +-[src: data:.....]----------------------+ +-[3D mesh]-+ | @house{castle, @@ -1006,7 +1009,6 @@ XR Fragments does this by detecting Bib(s)Tex, without introducing a new languag | #baroque@todo@house | | /|\ | | | ... | | / \ | | +----------------------------------------+ +--------+ | -]]>
    both #john@baroque-bib and BibTex @baroque{john} result in the same XRWG, however on top of that 2 tages (house and todo) are now associated with text/objectname/tag 'baroque'.
    As seen above, the XRWG can expand bibs (and the whole scene) to BibTeX.
    @@ -1060,22 +1062,21 @@ Some pointers for good UX (but not necessary to be XR Fragment compatible):
    The simplicity of appending metadata (and leveling the metadata-playfield between humans and machines) is also demonstrated by visual-meta in greater detail.
    Fictional chat: - Hey what about this: https://my.com/station.gltf#pos=0,0,1&rot=90,2,0&t=500,1000 - I'm checking it right now - I don't see everything..where's our text from yesterday? - Ah wait, that's tagged with tag 'draft' (and hidden)..hold on, try this: - https://my.com/station.gltf#.draft&pos=0,0,1&rot=90,2,0&t=500,1000 - how about we link the draft to the upcoming YELLO-event? - ok I'm adding #draft@YELLO - Yesterday I also came up with other usefull assocations between other texts in the scene: +<John> Hey what about this: https://my.com/station.gltf#pos=0,0,1&rot=90,2,0&t=500,1000 +<Sarah> I'm checking it right now +<Sarah> I don't see everything..where's our text from yesterday? +<John> Ah wait, that's tagged with tag 'draft' (and hidden)..hold on, try this: +<John> https://my.com/station.gltf#.draft&pos=0,0,1&rot=90,2,0&t=500,1000 +<Sarah> how about we link the draft to the upcoming YELLO-event? +<John> ok I'm adding #draft@YELLO +<Sarah> Yesterday I also came up with other usefull assocations between other texts in the scene: #event#YELLO #2025@YELLO - thanks, added. - Btw. I stumbled upon this spatial book which references station.gltf in some chapters: - https://thecommunity.org/forum/foo/mytrainstory.txt - interesting, I'm importing mytrainstory.txt into station.gltf - ah yes, chapter three points to trainterminal_2A in the scene, cool -]]> +<John> thanks, added. +<Sarah> Btw. I stumbled upon this spatial book which references station.gltf in some chapters: +<Sarah> https://thecommunity.org/forum/foo/mytrainstory.txt +<John> interesting, I'm importing mytrainstory.txt into station.gltf +<John> ah yes, chapter three points to trainterminal_2A in the scene, cool
    Default Data URI mimetype @@ -1111,7 +1112,7 @@ to connect text further with its environment ( setup links between textual/spati
    URL and Data URI - +--------------------------------------------------------------+ +------------------------+ | | | author.com/article.txt | | index.gltf | +------------------------+ | │ | | | @@ -1123,7 +1124,6 @@ to connect text further with its environment ( setup links between textual/spati | | +------------------------+ | | +--------------------------------------------------------------+ -]]> The enduser will only see welcome human and Hello friends rendered verbatim (see mimetype). The beauty is that text in Data URI automatically promotes rich copy-paste (retaining metadata). @@ -1135,14 +1135,14 @@ The XR Fragment-compatible browser can let the enduser access visual-meta(data)-
    XR Text example parser To prime the XRWG with text from plain text src-values, here's an example XR Text (de)multiplexer in javascript (which supports inline bibs & bibtex): -xrtext = { - expandBibs: (text) => { + expandBibs: (text) => { let bibs = { regex: /(#[a-zA-Z0-9_+@\-]+(#)?)/g, tags: {}} - text.replace( bibs.regex , (m,k,v) => { - tok = m.substr(1).split("@") + text.replace( bibs.regex , (m,k,v) => { + tok = m.substr(1).split("@") match = tok.shift() - if( tok.length ) tok.map( (t) => bibs.tags[t] = `@${t}{${match},\n}` ) + if( tok.length ) tok.map( (t) => bibs.tags[t] = `@${t}{${match},\n}` ) else if( match.substr(-1) == '#' ) bibs.tags[match] = `@{${match.replace(/#/,'')}}` else bibs.tags[match] = `@${match}{${match},\n}` @@ -1150,16 +1150,16 @@ The XR Fragment-compatible browser can let the enduser access visual-meta(data)- return text.replace( bibs.regex, '') + Object.values(bibs.tags).join('\n') }, - decode: (str) => { - // bibtex: ↓@ ↓ ↓property ↓end + decode: (str) => { + // bibtex: ↓@ ↓<tag|tag{phrase,|{ruler}> ↓property ↓end let pat = [ /@/, /^\S+[,{}]/, /},/, /}/ ] let tags = [], text='', i=0, prop='' let lines = xrtext.expandBibs(str).replace(/\r?\n/g,'\n').split(/\n/) - for( let i = 0; i < lines.length && !String(lines[i]).match( /^@/ ); i++ ) + for( let i = 0; i < lines.length && !String(lines[i]).match( /^@/ ); i++ ) text += lines[i]+'\n' bibtex = lines.join('\n').substr( text.length ) - bibtex.split( pat[0] ).map( (t) => { + bibtex.split( pat[0] ).map( (t) => { try{ let v = {} if( !(t = t.trim()) ) return @@ -1168,9 +1168,9 @@ The XR Fragment-compatible browser can let the enduser access visual-meta(data)- if( tag.match( /}$/ ) ) return tags.push({k: tag.replace(/}$/,''), v: {}}) t = t.substr( tag.length ) t.split( pat[2] ) - .map( kv => { - if( !(kv = kv.trim()) || kv == "}" ) return - v[ kv.match(/\s?(\S+)\s?=/)[1] ] = kv.substr( kv.indexOf("{")+1 ) + .map( kv => { + if( !(kv = kv.trim()) || kv == "}" ) return + v[ kv.match(/\s?(\S+)\s?=/)[1] ] = kv.substr( kv.indexOf("{")+1 ) }) tags.push( { k:tag, v } ) }catch(e){ console.error(e) } @@ -1178,8 +1178,8 @@ The XR Fragment-compatible browser can let the enduser access visual-meta(data)- return {text, tags} }, - encode: (text,tags) => { - let str = text+"\n" + encode: (text,tags) => { + let str = text+"\n" for( let i in tags ){ let item = tags[i] if( item.ruler ){ @@ -1193,12 +1193,11 @@ The XR Fragment-compatible browser can let the enduser access visual-meta(data)- return str } } -]]> The above functions (de)multiplexe text/metadata, expands bibs, (de)serialize bibtex and vice versa
    above can be used as a startingpoint for LLVM's to translate/steelman to a more formal form/language.
    -str = ` hello world here are some hashtagbibs followed by bibtex: @@ -1211,15 +1210,14 @@ here are some hashtagbibs followed by bibtex: asdf = {23423} }` -var {tags,text} = xrtext.decode(str) // demultiplex text & bibtex -tags.find( (t) => t.k == 'flap{' ).v.asdf = 1 // edit tag +var {tags,text} = xrtext.decode(str) // demultiplex text & bibtex +tags.find( (t) => t.k == 'flap{' ).v.asdf = 1 // edit tag tags.push({ k:'bar{', v:{abc:123} }) // add tag -console.log( xrtext.encode(text,tags) ) // multiplex text & bibtex back together -]]> +console.log( xrtext.encode(text,tags) ) // multiplex text & bibtex back together This expands to the following (hidden by default) BibTex appendix: -hello world here are some hashtagbibs followed by bibtex: @{some-section} @@ -1234,7 +1232,6 @@ here are some hashtagbibs followed by bibtex: @bar{ abc = {123} } -]]>
    when an XR browser updates the human text, a quick scan for nonmatching tags (@book{nonmatchingbook e.g.) should be performed and prompt the enduser for deleting them.
    @@ -1251,7 +1248,7 @@ here are some hashtagbibs followed by bibtex:
    due to the popularity, maturity and extensiveness of HTTP codes for client/server communication, non-HTTP protocols easily map to HTTP codes (ipfs ERR_NOT_FOUND maps to 404 e.g.)
    For example: - +────────────────────────────────────────────────────────+ │ │ │ index.gltf │ │ │ │ @@ -1263,14 +1260,13 @@ here are some hashtagbibs followed by bibtex: │ │ └ href@400: #clienterrortext │ │ │ └ ◻ offlinetext │ │ │ │ - │ └── ◻ embeddedObject <--------- the meshdata inside embeddedObject will (not) + │ └── ◻ embeddedObject <--------- the meshdata inside embeddedObject will (not) │ └ src: https://foo.io/bar.gltf │ be flushed when the request (does not) succeed. │ └ src@404: http://foo.io/bar.gltf │ So worstcase the 3D data (of the time of publishing index.gltf) │ └ src@400: https://archive.org/l2kj43.gltf │ will be displayed. │ │ +────────────────────────────────────────────────────────+ -]]>
    @@ -1302,7 +1298,7 @@ To filter out non-related objects one could take it a step further using filters The following demonstrates a simple video player: - +─────────────────────────────────────────────+ │ │ │ foo.usdz │ @@ -1310,19 +1306,18 @@ The following demonstrates a simple video player: │ │ │ │ ├── ◻ stopbutton │ │ │ ├ #: #-stopbutton │ - │ │ └ href: #player=stop&-stopbutton │ (stop and hide stop-button) + │ │ └ href: #player=stop&-stopbutton │ (stop and hide stop-button) │ │ │ │ └── ◻ plane │ │ ├ play: #t=l:0,10 │ │ ├ stop: #t=0,0 │ - │ ├ href: #player=play&stopbutton │ (play and show stop-button) + │ ├ href: #player=play&stopbutton │ (play and show stop-button) │ └ src: cat.mp4#{player} │ │ │ │ │ +─────────────────────────────────────────────+ -]]>
    diff --git a/doc/RFC_XR_Macros.txt b/doc/RFC_XR_Macros.txt index ab0dc15..556356c 100644 --- a/doc/RFC_XR_Macros.txt +++ b/doc/RFC_XR_Macros.txt @@ -3,7 +3,7 @@ Internet Engineering Task Force L.R. van Kammen -Internet-Draft 8 February 2024 +Internet-Draft 16 February 2024 Intended status: Informational @@ -38,7 +38,7 @@ Status of This Memo time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress." - This Internet-Draft will expire on 11 August 2024. + This Internet-Draft will expire on 19 August 2024. Copyright Notice @@ -53,7 +53,7 @@ Copyright Notice -van Kammen Expires 11 August 2024 [Page 1] +van Kammen Expires 19 August 2024 [Page 1] Internet-Draft XR Macros February 2024 @@ -109,13 +109,13 @@ Table of Contents -van Kammen Expires 11 August 2024 [Page 2] +van Kammen Expires 19 August 2024 [Page 2] Internet-Draft XR Macros February 2024 - 3. Metadata-values can contain the | symbol to 🎲 roundrobin variable - values (!toggleme: fog=0,10|fog=0,1000 e.g.) + 3. Metadata-values can contain the | symbol to 🎲 roundrobin + variable values (!toggleme: fog=0,10|fog=0,1000 e.g.) 4. XR Macros acts as simple eventhandlers for URI Fragments: they are automatically published on the (XR Fragments (https://xrfragment.org)) hashbus, to act as events (so more @@ -165,7 +165,7 @@ Internet-Draft XR Macros February 2024 -van Kammen Expires 11 August 2024 [Page 3] +van Kammen Expires 19 August 2024 [Page 3] Internet-Draft XR Macros February 2024 @@ -221,7 +221,7 @@ Internet-Draft XR Macros February 2024 -van Kammen Expires 11 August 2024 [Page 4] +van Kammen Expires 19 August 2024 [Page 4] Internet-Draft XR Macros February 2024 @@ -277,7 +277,7 @@ Internet-Draft XR Macros February 2024 -van Kammen Expires 11 August 2024 [Page 5] +van Kammen Expires 19 August 2024 [Page 5] Internet-Draft XR Macros February 2024 @@ -333,7 +333,7 @@ click object with (`!clickme`:`!foo|!bar|!flop` e.g.) -van Kammen Expires 11 August 2024 [Page 6] +van Kammen Expires 19 August 2024 [Page 6] Internet-Draft XR Macros February 2024 @@ -375,7 +375,7 @@ Internet-Draft XR Macros February 2024 | | (games,VR,AR e.g.), should be as high as | | | possible | +---------------+---------------------------------------------------+ - | ◻ | ascii representation of an 3D object/mesh | + | ◻ | ascii representation of an 3D object/mesh | +---------------+---------------------------------------------------+ | (un)obtrusive | obtrusive: wrapping human text/thought in | | | XML/HTML/JSON obfuscates human text into | @@ -389,4 +389,4 @@ Internet-Draft XR Macros February 2024 -van Kammen Expires 11 August 2024 [Page 7] +van Kammen Expires 19 August 2024 [Page 7] diff --git a/doc/RFC_XR_Macros.xml b/doc/RFC_XR_Macros.xml index 0150e79..b08a4f2 100644 --- a/doc/RFC_XR_Macros.xml +++ b/doc/RFC_XR_Macros.xml @@ -282,17 +282,16 @@ Macros also act as events, so more serious scripting languages can react to them
    Event Bubble-flow click object with (!clickme:AR or !clickme: !reset e.g.) - ◻ │ └── does current object contain this property-key (`AR` or `!reset` e.g.)? └── no: is there any (root)object containing property `AR` └── yes: evaluate its (roundrobin) XR macro-value(s) (and exit) └── no: trigger URL: #AR -]]> click object with (!clickme:#AR|#VR e.g.) - ◻ │ └── apply the roundrobin (rotate the options, value `#AR` becomes `#VR` upon next click) └── is there any object with property-key (`#AR` e.g.)? @@ -300,7 +299,6 @@ Macros also act as events, so more serious scripting languages can react to them └── yes: apply its value to the scene, and update the URL to `#AR` click object with (`!clickme`:`!foo|!bar|!flop` e.g.) -]]> ◻ │
    diff --git a/src/3rd/js/aframe/index.js b/src/3rd/js/aframe/index.js index b46f015..f52f6fd 100644 --- a/src/3rd/js/aframe/index.js +++ b/src/3rd/js/aframe/index.js @@ -100,6 +100,7 @@ window.AFRAME.registerComponent('xrf', { let isLocal = url.match(/^#/) let hasPos = url.match(/pos=/) let fastFadeMs = 200 + if( !AFRAME.fade ) return p.resolve() if( isLocal ){ if( hasPos ){ diff --git a/src/3rd/js/pubsub.js b/src/3rd/js/pubsub.js index 37a753a..499226f 100644 --- a/src/3rd/js/pubsub.js +++ b/src/3rd/js/pubsub.js @@ -25,9 +25,10 @@ xrf.addEventListener = function(eventName, callback, opts) { this._listeners[eventName].push(callback); // sort this._listeners[eventName] = this._listeners[eventName].sort( (a,b) => a.opts.weight > b.opts.weight ) - return () => { + callback.unlisten = () => { this._listeners[eventName] = this._listeners[eventName].filter( (c) => c != callback ) } + return callback.unlisten }; xrf.emit = function(eventName, data){ @@ -76,7 +77,8 @@ xrf.emit.promise = function(e, opts){ } xrf.addEventListener('reset', () => { -// *TODO* do this nicely -// xrf._listeners['renderPost'] = [] -// xrf._listeners['render'] = [] + let events = ['renderPost'] + events.map( (e) => { + if( xrf._listeners[e] ) xrf._listeners[e].map( (r) => r.unlisten && r.unlisten() ) + }) }) diff --git a/src/3rd/js/three/util/optimize.js b/src/3rd/js/three/util/optimize.js index 18a4764..4a6a9a7 100644 --- a/src/3rd/js/three/util/optimize.js +++ b/src/3rd/js/three/util/optimize.js @@ -11,7 +11,7 @@ xrf.optimize = (opts) => { // check unused animations xrf.optimize.checkAnimations = (opts) => { - console.log("TODO: fix freezeUnAnimatedObjects for SRC's") + if( xrf.debug ) console.log("TODO: fix freezeUnAnimatedObjects for SRC's") return xrf.optimize let {model} = opts @@ -35,7 +35,7 @@ xrf.optimize.checkAnimations = (opts) => { } xrf.optimize.freezeUnAnimatedObjects = (opts) => { - console.log("TODO: fix freezeUnAnimatedObjects for SRC's") + if( xrf.todo ) console.log("TODO: fix freezeUnAnimatedObjects for SRC's") return xrf.optimize let {model} = opts diff --git a/src/3rd/js/three/xrf/#.js b/src/3rd/js/three/xrf/#.js index a940b99..bbadc76 100644 --- a/src/3rd/js/three/xrf/#.js +++ b/src/3rd/js/three/xrf/#.js @@ -4,12 +4,7 @@ xrf.frag.defaultPredefinedViews = (opts) => { let {scene,model} = opts; scene.traverse( (n) => { if( n.userData && n.userData['#'] ){ - let frag = xrf.URI.parse( n.userData['#'] ) - if( !n.parent && document.location.hash.length < 2){ - xrf.navigator.to( n.userData['#'] ) // evaluate default XR fragments (global-level) - }else{ - xrf.hashbus.pub( n.userData['#'], n ) // evaluate default XR fragments (node-level) - } + xrf.hashbus.pub( n.userData['#'], n ) // evaluate default XR fragments without affecting URL } }) } diff --git a/src/3rd/js/three/xrf/dynamic/filter.js b/src/3rd/js/three/xrf/dynamic/filter.js index ae834a5..771f8ac 100644 --- a/src/3rd/js/three/xrf/dynamic/filter.js +++ b/src/3rd/js/three/xrf/dynamic/filter.js @@ -10,7 +10,7 @@ const doFilter = (opts) => { xrf.addEventListener('dynamicKey', doFilter ) xrf.addEventListener('dynamicKeyValue', (opts) => { - console.log("*TODO* filter integers only") + if( xrf.debug ) console.log("*TODO* filter integers only") // doFilter(opts) }) diff --git a/src/3rd/js/three/xrf/src/fbx.js b/src/3rd/js/three/xrf/src/fbx.js new file mode 100644 index 0000000..7c79857 --- /dev/null +++ b/src/3rd/js/three/xrf/src/fbx.js @@ -0,0 +1,27 @@ +/* + * mimetype: model/gltf+json + */ + +xrf.frag.src.type['fbx'] = function( url, opts ){ + return new Promise( async (resolve,reject) => { + let {mesh,src} = opts + let {urlObj,dir,file,hash,ext} = xrf.parseUrl(url) + let loader + + //let {THREE} = await import('https://unpkg.com/three@0.161.0/build/three.module.js') + //let { FBXLoader } = await import('three/addons/loaders/FBXLoader.js') + + //const Loader = xrf.loaders[ext] + //if( !Loader ) throw 'xrfragment: no loader passed to xrfragment for extension .'+ext + //if( !dir.match("://") ){ // force relative path + // dir = dir[0] == './' ? dir : `./${dir}` + // loader = new Loader().setPath( dir ) + //}else loader = new Loader() + + //loader.load(url, (model) => { + // model.isSRC = true + // resolve(model) + //}) + }) +} + diff --git a/test/generated/test.js b/test/generated/test.js index 5800957..e9dd629 100644 --- a/test/generated/test.js +++ b/test/generated/test.js @@ -1,6 +1,13 @@ var $hx_exports = typeof exports != "undefined" ? exports : typeof window != "undefined" ? window : typeof self != "undefined" ? self : this; (function ($global) { "use strict"; $hx_exports["xrfragment"] = $hx_exports["xrfragment"] || {}; +var $estr = function() { return js_Boot.__string_rec(this,''); },$hxEnums = $hxEnums || {},$_; +function $extend(from, fields) { + var proto = Object.create(from); + for (var name in fields) proto[name] = fields[name]; + if( fields.toString !== Object.prototype.toString ) proto.toString = fields.toString; + return proto; +} var EReg = function(r,opt) { this.r = new RegExp(r,opt.split("u").join("")); }; @@ -14,6 +21,26 @@ EReg.prototype = { this.r.s = s; return this.r.m != null; } + ,matched: function(n) { + if(this.r.m != null && n >= 0 && n < this.r.m.length) { + return this.r.m[n]; + } else { + throw haxe_Exception.thrown("EReg::matched"); + } + } + ,matchedRight: function() { + if(this.r.m == null) { + throw haxe_Exception.thrown("No string matched"); + } + var sz = this.r.m.index + this.r.m[0].length; + return HxOverrides.substr(this.r.s,sz,this.r.s.length - sz); + } + ,matchedPos: function() { + if(this.r.m == null) { + throw haxe_Exception.thrown("No string matched"); + } + return { pos : this.r.m.index, len : this.r.m[0].length}; + } ,split: function(s) { var d = "#__delim__#"; return s.replace(this.r,d).split(d); @@ -53,6 +80,25 @@ Reflect.field = function(o,field) { return null; } }; +Reflect.getProperty = function(o,field) { + var tmp; + if(o == null) { + return null; + } else { + var tmp1; + if(o.__properties__) { + tmp = o.__properties__["get_" + field]; + tmp1 = tmp; + } else { + tmp1 = false; + } + if(tmp1) { + return o[tmp](); + } else { + return o[field]; + } + } +}; Reflect.fields = function(o) { var a = []; if(o != null) { @@ -65,6 +111,21 @@ Reflect.fields = function(o) { } return a; }; +Reflect.isObject = function(v) { + if(v == null) { + return false; + } + var t = typeof(v); + if(!(t == "string" || t == "object" && v.__enum__ == null)) { + if(t == "function") { + return (v.__name__ || v.__ename__) != null; + } else { + return false; + } + } else { + return true; + } +}; Reflect.deleteField = function(o,field) { if(!Object.prototype.hasOwnProperty.call(o,field)) { return false; @@ -111,6 +172,10 @@ Std.parseInt = function(x) { } return null; }; +var StringBuf = function() { + this.b = ""; +}; +StringBuf.__name__ = true; var StringTools = function() { }; StringTools.__name__ = true; StringTools.isSpace = function(s,pos) { @@ -144,20 +209,24 @@ StringTools.rtrim = function(s) { StringTools.trim = function(s) { return StringTools.ltrim(StringTools.rtrim(s)); }; +StringTools.replace = function(s,sub,by) { + return s.split(sub).join(by); +}; var Test = function() { }; Test.__name__ = true; Test.main = function() { Test.test("url.json",[{ fn : "url", expect : { fn : "testPredefinedView", input : "mypredefinedview", out : true}, label : "test predefined view executed", data : "http://foo.com?foo=1#mypredefinedview"},{ fn : "url", expect : { fn : "testPredefinedView", input : "another", out : true}, label : "test predefined view executed (multiple)", data : "http://foo.com?foo=1#mypredefinedview&another"},{ fn : "url", expect : { fn : "testPredefinedView", input : "mypredefinedview", out : true}, label : "test predefined view executed (multiple)", data : "http://foo.com?foo=1#mypredefinedview&another"},{ fn : "url", expect : { fn : "testParsed", input : "mycustom", out : true}, label : "test custom property", data : "http://foo.com?foo=1#mycustom=foo"}]); Test.test("pos.json",[{ fn : "url", expect : { fn : "equal.string", input : "pos", out : "1.2,2.2"}, label : "equal.string", data : "http://foo.com?foo=1#pos=1.2,2.2"},{ fn : "url", expect : { fn : "equal.xyz", input : "pos", out : "1.2,2.2,3"}, label : "equal.xyz", data : "http://foo.com?foo=1#pos=1.2,2.2,3"},{ fn : "url", expect : { fn : "equal.xyz", input : "pos", out : "1,2,3"}, label : "pos equal.xyz", data : "http://foo.com?foo=1#pos=1,2,3"},{ fn : "url", expect : { fn : "equal.string", input : "pos", out : "world2"}, label : "pos equal.xyz", data : "http://foo.com?foo=1#pos=world2"}]); - Test.test("t.json",[{ fn : "url", expect : { fn : "equal.x", input : "t", out : "1"}, label : "a equal.x", data : "http://foo.com?foo=1#t=1"},{ fn : "url", expect : { fn : "equal.x", input : "t", out : "-1"}, label : "a equal.x", data : "http://foo.com?foo=1#t=-1"},{ fn : "url", expect : { fn : "equal.x", input : "t", out : "-1.02"}, label : "a equal.x", data : "http://foo.com?foo=1#t=-1.02"},{ fn : "url", expect : { fn : "equal.xy", input : "t", out : "1,2"}, label : "a equal.xy", data : "http://foo.com?foo=1#t=1,2,3"},{ fn : "url", expect : { fn : "equal.xyz", input : "t", out : "1,2,3"}, label : "a equal.xyz", data : "http://foo.com?foo=1#t=1,2,3"},{ fn : "url", expect : { fn : "equal.xyz", input : "t", out : "1,-2,3"}, label : "a equal.xyz", data : "http://foo.com?foo=1#t=1,-2,3"},{ fn : "url", expect : { fn : "equal.xy", input : "t", out : "1,100"}, label : "a equal.xy", data : "http://foo.com?foo=1#t=1,100"},{ fn : "url", expect : { fn : "testBrowserOverride", input : "t", out : true}, label : "browser URI can override t (defined in asset)", data : "http://foo.com?foo=1#t=2,500"},{ fn : "url", expect : { fn : "equal.mediafragmentT", input : "3", out : "500"}, label : "a equal.mediafragment", data : "http://foo.com?foo=1#t=1,100,400,500*1.2,2.3"},{ fn : "url", expect : { fn : "equal.mediafragmentTSpd", input : "1", out : "2.3"}, label : "a equal.mediafragmentSpeed", data : "http://foo.com?foo=1#t=1,100,400,500*1.2,2.3"}]); - Test.test("xywh.json",[{ fn : "url", expect : { fn : "equal.mediafragmentXYWH", input : "2", out : "1"}, label : "xywh", data : "http://foo.com?foo=1#xywh=0,0,1,1"},{ fn : "url", expect : { fn : "equal.mediafragmentXYWH", input : "3", out : "500"}, label : "a equal.mediafragment", data : "http://foo.com?foo=1#xywh=1,100,400,500*1.2,2.3"},{ fn : "url", expect : { fn : "equal.mediafragmentXYWHSpd", input : "1", out : "2.3"}, label : "a equal.mediafragmentSpeed", data : "http://foo.com?foo=1#xywh=1,100,400,500*1.2,2.3"}]); - Test.test("filter.selectors.json",[{ fn : "url", expect : { fn : "testParsed", input : "myid", out : true}, label : "myid exists", data : "http://foo.com?foo=1#foo*&-sometag&-someid&myid"},{ fn : "url", expect : { fn : "testParsed", input : "tag", out : true}, label : "tag exists", data : "http://foo.com?foo=1#tag=bar"},{ fn : "url", expect : { fn : "testParsed", input : "tag", out : true}, label : "tag exists", data : "http://foo.com?foo=1#-tag=bar"},{ fn : "url", expect : { fn : "testParsed", input : "price", out : true}, label : "filter test", data : "http://foo.com?foo=1#price=>2"},{ fn : "filter", expect : { fn : "testProperty", input : ["tag","bar"], out : true}, data : "tag=bar"},{ fn : "filter", expect : { fn : "testProperty", input : ["tag","foo"], out : false}, data : "-tag=foo"},{ fn : "filter", expect : { fn : "testProperty", input : ["tag","foo"], out : false}, data : "-tag*=foo"},{ fn : "filter", expect : { fn : "testProperty", input : ["tag","3"], out : false}, data : "-tag=>2"},{ fn : "filter", expect : { fn : "testProperty", input : ["price","1"], out : false}, data : "price=>2"},{ fn : "filter", expect : { fn : "testProperty", input : ["price","5"], out : false}, data : "price=<2"},{ fn : "filter", expect : { fn : "testProperty", input : ["price","1"], out : true}, data : "price=<2"},{ fn : "url", expect : { fn : "testFilterDeep", input : ["foo"], out : 1}, label : "foo should be deep", data : "#foo*"},{ fn : "url", expect : { fn : "testFilterDeep", input : ["foo"], out : 2}, label : "foo should be deep incl. embeds", data : "#foo**"}]); + Test.test("t.json",[{ fn : "url", expect : { fn : "equal.x", input : "t", out : "1"}, label : "a equal.x", data : "http://foo.com?foo=1#t=1"},{ fn : "url", expect : { fn : "equal.x", input : "t", out : "-1"}, label : "a equal.x", data : "http://foo.com?foo=1#t=-1"},{ fn : "url", expect : { fn : "equal.x", input : "t", out : "-1.02"}, label : "a equal.x", data : "http://foo.com?foo=1#t=-1.02"},{ fn : "url", expect : { fn : "equal.xy", input : "t", out : "1,2"}, label : "a equal.xy", data : "http://foo.com?foo=1#t=1,2,3"},{ fn : "url", expect : { fn : "equal.xyz", input : "t", out : "1,2,3"}, label : "a equal.xyz", data : "http://foo.com?foo=1#t=1,2,3"},{ fn : "url", expect : { fn : "equal.xyz", input : "t", out : "1,-2,3"}, label : "a equal.xyz", data : "http://foo.com?foo=1#t=1,-2,3"},{ fn : "url", expect : { fn : "equal.xy", input : "t", out : "1,100"}, label : "a equal.xy", data : "http://foo.com?foo=1#t=1,100"},{ fn : "url", expect : { fn : "testBrowserOverride", input : "t", out : true}, label : "browser URI can override t (defined in asset)", data : "http://foo.com?foo=1#t=2,500"},{ fn : "url", expect : { fn : "equal.mediafragmentT", input : "3", out : "500"}, label : "a equal.mediafragment", data : "http://foo.com?foo=1#t=1,100,400,500"},{ fn : "url", expect : { fn : "equal.mediafragmentT", input : "3", out : "500"}, label : "a equal.mediafragment loop", data : "http://foo.com?foo=1#t=l:1,100,400,500"}]); + Test.test("s.json",[{ fn : "url", expect : { fn : "equal.x", input : "s", out : "1"}, label : "playback speed", data : "http://foo.com?foo=1#s=1"},{ fn : "url", expect : { fn : "equal.x", input : "s", out : "0.5"}, label : "playback speed", data : "http://foo.com?foo=1#s=0.5"},{ fn : "url", expect : { fn : "equal.x", input : "s", out : "-0.5"}, label : "playback speed", data : "http://foo.com?foo=1#s=-0.5"}]); + Test.test("uv.json",[{ fn : "url", expect : { fn : "equal.xy", input : "uv", out : "1.2,2.2"}, label : "equal.string uv", data : "http://foo.com?foo=1#uv=1.2,2.2"},{ fn : "url", expect : { fn : "equal.xyz", input : "uv", out : "1.2,2.2,1"}, label : "equal.string uv", data : "http://foo.com?foo=1#uv=1.2,2.2,+1,+1"}]); + Test.test("filter.selectors.json",[{ fn : "url", expect : { fn : "testParsed", input : "myid", out : true}, label : "myid exists", data : "http://foo.com?foo=1#foo*&-sometag&-someid&myid"},{ fn : "url", expect : { fn : "testParsed", input : "tag", out : true}, label : "tag exists", data : "http://foo.com?foo=1#tag=bar"},{ fn : "url", expect : { fn : "testParsed", input : "tag", out : true}, label : "tag exists", data : "http://foo.com?foo=1#-tag=bar"},{ fn : "url", expect : { fn : "testParsed", input : "price", out : true}, label : "filter test", data : "http://foo.com?foo=1#price=>2"},{ fn : "filter", expect : { fn : "testProperty", input : ["tag","bar"], out : true}, data : "tag=bar"},{ fn : "filter", expect : { fn : "testProperty", input : ["tag","foo"], out : false}, data : "-tag=foo"},{ fn : "filter", expect : { fn : "testProperty", input : ["tag","foo"], out : false}, data : "-tag*=foo"},{ fn : "filter", expect : { fn : "testProperty", input : ["tag","3"], out : false}, data : "-tag=>2"},{ fn : "filter", expect : { fn : "testProperty", input : ["price","1"], out : false}, data : "price=>2"},{ fn : "filter", expect : { fn : "testProperty", input : ["price","5"], out : false}, data : "price=<2"},{ fn : "filter", expect : { fn : "testProperty", input : ["price","1"], out : true}, data : "price=<2"},{ fn : "url", expect : { fn : "testFilterDeep", input : ["foo"], out : 1}, label : "foo should be deep", data : "#foo*"}]); if(Test.errors > 1) { - console.log("src/Test.hx:24:","\n-----\n[ ❌] " + Test.errors + " errors :/"); + console.log("src/Test.hx:25:","\n-----\n[ ❌] " + Test.errors + " errors :/"); } }; Test.test = function(topic,spec) { - console.log("src/Test.hx:28:","\n[.] running " + topic); + console.log("src/Test.hx:29:","\n[ . ] running " + topic); var Filter = xrfragment_Filter; var _g = 0; var _g1 = spec.length; @@ -215,14 +284,11 @@ Test.test = function(topic,spec) { if(item.expect.fn == "equal.mediafragmentT") { valid = Test.equalMediaFragment(res,item,"t"); } - if(item.expect.fn == "equal.mediafragmentXYWH") { - valid = Test.equalMediaFragment(res,item,"xywh"); + if(item.expect.fn == "equal.mediafragmentUV") { + valid = Test.equalMediaFragment(res,item,"uv"); } - if(item.expect.fn == "equal.mediafragmentTSpd") { - valid = Test.equalMediaFragmentSpd(res,item,"t"); - } - if(item.expect.fn == "equal.mediafragmentXYWHSpd") { - valid = Test.equalMediaFragmentSpd(res,item,"xywh"); + if(item.expect.fn == "equal.mediafragmentS") { + valid = Test.equalMediaFragment(res,item,"s"); } if(item.expect.fn == "testFilterRoot") { valid = Object.prototype.hasOwnProperty.call(res,item.expect.input[0]) && res[item.expect.input[0]].filter.get().root == item.expect.out; @@ -268,16 +334,55 @@ Test.equalMediaFragment = function(res,item,key) { if(!item.expect.out && !res[item.expect.input]) { return true; } else { - return res[key].floats[Std.parseInt(item.expect.input)] == Std.parseInt(item.expect.out); + return res[key].floats[Std.parseInt(item.expect.input)] == parseFloat(item.expect.out); } }; -Test.equalMediaFragmentSpd = function(res,item,key) { - if(!item.expect.out && !res[item.expect.input]) { - return true; +var haxe_Exception = function(message,previous,native) { + Error.call(this,message); + this.message = message; + this.__previousException = previous; + this.__nativeException = native != null ? native : this; +}; +haxe_Exception.__name__ = true; +haxe_Exception.caught = function(value) { + if(((value) instanceof haxe_Exception)) { + return value; + } else if(((value) instanceof Error)) { + return new haxe_Exception(value.message,null,value); } else { - return res[key].speed[Std.parseInt(item.expect.input)] == parseFloat(item.expect.out); + return new haxe_ValueException(value,null,value); } }; +haxe_Exception.thrown = function(value) { + if(((value) instanceof haxe_Exception)) { + return value.get_native(); + } else if(((value) instanceof Error)) { + return value; + } else { + var e = new haxe_ValueException(value); + return e; + } +}; +haxe_Exception.__super__ = Error; +haxe_Exception.prototype = $extend(Error.prototype,{ + unwrap: function() { + return this.__nativeException; + } + ,get_native: function() { + return this.__nativeException; + } + ,__properties__: {get_native:"get_native"} +}); +var haxe__$Template_TemplateExpr = $hxEnums["haxe._Template.TemplateExpr"] = { __ename__:true,__constructs__:null + ,OpVar: ($_=function(v) { return {_hx_index:0,v:v,__enum__:"haxe._Template.TemplateExpr",toString:$estr}; },$_._hx_name="OpVar",$_.__params__ = ["v"],$_) + ,OpExpr: ($_=function(expr) { return {_hx_index:1,expr:expr,__enum__:"haxe._Template.TemplateExpr",toString:$estr}; },$_._hx_name="OpExpr",$_.__params__ = ["expr"],$_) + ,OpIf: ($_=function(expr,eif,eelse) { return {_hx_index:2,expr:expr,eif:eif,eelse:eelse,__enum__:"haxe._Template.TemplateExpr",toString:$estr}; },$_._hx_name="OpIf",$_.__params__ = ["expr","eif","eelse"],$_) + ,OpStr: ($_=function(str) { return {_hx_index:3,str:str,__enum__:"haxe._Template.TemplateExpr",toString:$estr}; },$_._hx_name="OpStr",$_.__params__ = ["str"],$_) + ,OpBlock: ($_=function(l) { return {_hx_index:4,l:l,__enum__:"haxe._Template.TemplateExpr",toString:$estr}; },$_._hx_name="OpBlock",$_.__params__ = ["l"],$_) + ,OpForeach: ($_=function(expr,loop) { return {_hx_index:5,expr:expr,loop:loop,__enum__:"haxe._Template.TemplateExpr",toString:$estr}; },$_._hx_name="OpForeach",$_.__params__ = ["expr","loop"],$_) + ,OpMacro: ($_=function(name,params) { return {_hx_index:6,name:name,params:params,__enum__:"haxe._Template.TemplateExpr",toString:$estr}; },$_._hx_name="OpMacro",$_.__params__ = ["name","params"],$_) +}; +haxe__$Template_TemplateExpr.__constructs__ = [haxe__$Template_TemplateExpr.OpVar,haxe__$Template_TemplateExpr.OpExpr,haxe__$Template_TemplateExpr.OpIf,haxe__$Template_TemplateExpr.OpStr,haxe__$Template_TemplateExpr.OpBlock,haxe__$Template_TemplateExpr.OpForeach,haxe__$Template_TemplateExpr.OpMacro]; var haxe_iterators_ArrayIterator = function(array) { this.current = 0; this.array = array; @@ -291,6 +396,587 @@ haxe_iterators_ArrayIterator.prototype = { return this.array[this.current++]; } }; +var haxe_Template = function(str) { + var tokens = this.parseTokens(str); + this.expr = this.parseBlock(tokens); + if(!tokens.isEmpty()) { + throw haxe_Exception.thrown("Unexpected '" + Std.string(tokens.first().s) + "'"); + } +}; +haxe_Template.__name__ = true; +haxe_Template.prototype = { + execute: function(context,macros) { + this.macros = macros == null ? { } : macros; + this.context = context; + this.stack = new haxe_ds_List(); + this.buf = new StringBuf(); + this.run(this.expr); + return this.buf.b; + } + ,resolve: function(v) { + if(v == "__current__") { + return this.context; + } + if(Reflect.isObject(this.context)) { + var value = Reflect.getProperty(this.context,v); + if(value != null || Object.prototype.hasOwnProperty.call(this.context,v)) { + return value; + } + } + var _g_head = this.stack.h; + while(_g_head != null) { + var val = _g_head.item; + _g_head = _g_head.next; + var ctx = val; + var value = Reflect.getProperty(ctx,v); + if(value != null || Object.prototype.hasOwnProperty.call(ctx,v)) { + return value; + } + } + return Reflect.field(haxe_Template.globals,v); + } + ,parseTokens: function(data) { + var tokens = new haxe_ds_List(); + while(haxe_Template.splitter.match(data)) { + var p = haxe_Template.splitter.matchedPos(); + if(p.pos > 0) { + tokens.add({ p : HxOverrides.substr(data,0,p.pos), s : true, l : null}); + } + if(HxOverrides.cca(data,p.pos) == 58) { + tokens.add({ p : HxOverrides.substr(data,p.pos + 2,p.len - 4), s : false, l : null}); + data = haxe_Template.splitter.matchedRight(); + continue; + } + var parp = p.pos + p.len; + var npar = 1; + var params = []; + var part = ""; + while(true) { + var c = HxOverrides.cca(data,parp); + ++parp; + if(c == 40) { + ++npar; + } else if(c == 41) { + --npar; + if(npar <= 0) { + break; + } + } else if(c == null) { + throw haxe_Exception.thrown("Unclosed macro parenthesis"); + } + if(c == 44 && npar == 1) { + params.push(part); + part = ""; + } else { + part += String.fromCodePoint(c); + } + } + params.push(part); + tokens.add({ p : haxe_Template.splitter.matched(2), s : false, l : params}); + data = HxOverrides.substr(data,parp,data.length - parp); + } + if(data.length > 0) { + tokens.add({ p : data, s : true, l : null}); + } + return tokens; + } + ,parseBlock: function(tokens) { + var l = new haxe_ds_List(); + while(true) { + var t = tokens.first(); + if(t == null) { + break; + } + if(!t.s && (t.p == "end" || t.p == "else" || HxOverrides.substr(t.p,0,7) == "elseif ")) { + break; + } + l.add(this.parse(tokens)); + } + if(l.length == 1) { + return l.first(); + } + return haxe__$Template_TemplateExpr.OpBlock(l); + } + ,parse: function(tokens) { + var t = tokens.pop(); + var p = t.p; + if(t.s) { + return haxe__$Template_TemplateExpr.OpStr(p); + } + if(t.l != null) { + var pe = new haxe_ds_List(); + var _g = 0; + var _g1 = t.l; + while(_g < _g1.length) { + var p1 = _g1[_g]; + ++_g; + pe.add(this.parseBlock(this.parseTokens(p1))); + } + return haxe__$Template_TemplateExpr.OpMacro(p,pe); + } + var kwdEnd = function(kwd) { + var pos = -1; + var length = kwd.length; + if(HxOverrides.substr(p,0,length) == kwd) { + pos = length; + var _g_offset = 0; + var _g_s = HxOverrides.substr(p,length,null); + while(_g_offset < _g_s.length) { + var c = _g_s.charCodeAt(_g_offset++); + if(c == 32) { + ++pos; + } else { + break; + } + } + } + return pos; + }; + var pos = kwdEnd("if"); + if(pos > 0) { + p = HxOverrides.substr(p,pos,p.length - pos); + var e = this.parseExpr(p); + var eif = this.parseBlock(tokens); + var t = tokens.first(); + var eelse; + if(t == null) { + throw haxe_Exception.thrown("Unclosed 'if'"); + } + if(t.p == "end") { + tokens.pop(); + eelse = null; + } else if(t.p == "else") { + tokens.pop(); + eelse = this.parseBlock(tokens); + t = tokens.pop(); + if(t == null || t.p != "end") { + throw haxe_Exception.thrown("Unclosed 'else'"); + } + } else { + t.p = HxOverrides.substr(t.p,4,t.p.length - 4); + eelse = this.parse(tokens); + } + return haxe__$Template_TemplateExpr.OpIf(e,eif,eelse); + } + var pos = kwdEnd("foreach"); + if(pos >= 0) { + p = HxOverrides.substr(p,pos,p.length - pos); + var e = this.parseExpr(p); + var efor = this.parseBlock(tokens); + var t = tokens.pop(); + if(t == null || t.p != "end") { + throw haxe_Exception.thrown("Unclosed 'foreach'"); + } + return haxe__$Template_TemplateExpr.OpForeach(e,efor); + } + if(haxe_Template.expr_splitter.match(p)) { + return haxe__$Template_TemplateExpr.OpExpr(this.parseExpr(p)); + } + return haxe__$Template_TemplateExpr.OpVar(p); + } + ,parseExpr: function(data) { + var l = new haxe_ds_List(); + var expr = data; + while(haxe_Template.expr_splitter.match(data)) { + var p = haxe_Template.expr_splitter.matchedPos(); + var k = p.pos + p.len; + if(p.pos != 0) { + l.add({ p : HxOverrides.substr(data,0,p.pos), s : true}); + } + var p1 = haxe_Template.expr_splitter.matched(0); + l.add({ p : p1, s : p1.indexOf("\"") >= 0}); + data = haxe_Template.expr_splitter.matchedRight(); + } + if(data.length != 0) { + var _g_offset = 0; + var _g_s = data; + while(_g_offset < _g_s.length) { + var _g1_key = _g_offset; + var _g1_value = _g_s.charCodeAt(_g_offset++); + var i = _g1_key; + var c = _g1_value; + if(c != 32) { + l.add({ p : HxOverrides.substr(data,i,null), s : true}); + break; + } + } + } + var e; + try { + e = this.makeExpr(l); + if(!l.isEmpty()) { + throw haxe_Exception.thrown(l.first().p); + } + } catch( _g ) { + var _g1 = haxe_Exception.caught(_g).unwrap(); + if(typeof(_g1) == "string") { + var s = _g1; + throw haxe_Exception.thrown("Unexpected '" + s + "' in " + expr); + } else { + throw _g; + } + } + return function() { + try { + return e(); + } catch( _g ) { + var exc = haxe_Exception.caught(_g).unwrap(); + throw haxe_Exception.thrown("Error : " + Std.string(exc) + " in " + expr); + } + }; + } + ,makeConst: function(v) { + haxe_Template.expr_trim.match(v); + v = haxe_Template.expr_trim.matched(1); + if(HxOverrides.cca(v,0) == 34) { + var str = HxOverrides.substr(v,1,v.length - 2); + return function() { + return str; + }; + } + if(haxe_Template.expr_int.match(v)) { + var i = Std.parseInt(v); + return function() { + return i; + }; + } + if(haxe_Template.expr_float.match(v)) { + var f = parseFloat(v); + return function() { + return f; + }; + } + var me = this; + return function() { + return me.resolve(v); + }; + } + ,makePath: function(e,l) { + var p = l.first(); + if(p == null || p.p != ".") { + return e; + } + l.pop(); + var field = l.pop(); + if(field == null || !field.s) { + throw haxe_Exception.thrown(field.p); + } + var f = field.p; + haxe_Template.expr_trim.match(f); + f = haxe_Template.expr_trim.matched(1); + return this.makePath(function() { + return Reflect.field(e(),f); + },l); + } + ,makeExpr: function(l) { + return this.makePath(this.makeExpr2(l),l); + } + ,skipSpaces: function(l) { + var p = l.first(); + while(p != null) { + var _g_offset = 0; + var _g_s = p.p; + while(_g_offset < _g_s.length) { + var c = _g_s.charCodeAt(_g_offset++); + if(c != 32) { + return; + } + } + l.pop(); + p = l.first(); + } + } + ,makeExpr2: function(l) { + this.skipSpaces(l); + var p = l.pop(); + this.skipSpaces(l); + if(p == null) { + throw haxe_Exception.thrown(""); + } + if(p.s) { + return this.makeConst(p.p); + } + switch(p.p) { + case "!": + var e = this.makeExpr(l); + return function() { + var v = e(); + if(v != null) { + return v == false; + } else { + return true; + } + }; + case "(": + this.skipSpaces(l); + var e1 = this.makeExpr(l); + this.skipSpaces(l); + var p1 = l.pop(); + if(p1 == null || p1.s) { + throw haxe_Exception.thrown(p1); + } + if(p1.p == ")") { + return e1; + } + this.skipSpaces(l); + var e2 = this.makeExpr(l); + this.skipSpaces(l); + var p2 = l.pop(); + this.skipSpaces(l); + if(p2 == null || p2.p != ")") { + throw haxe_Exception.thrown(p2); + } + switch(p1.p) { + case "!=": + return function() { + return e1() != e2(); + }; + case "&&": + return function() { + return e1() && e2(); + }; + case "*": + return function() { + return e1() * e2(); + }; + case "+": + return function() { + return e1() + e2(); + }; + case "-": + return function() { + return e1() - e2(); + }; + case "/": + return function() { + return e1() / e2(); + }; + case "<": + return function() { + return e1() < e2(); + }; + case "<=": + return function() { + return e1() <= e2(); + }; + case "==": + return function() { + return e1() == e2(); + }; + case ">": + return function() { + return e1() > e2(); + }; + case ">=": + return function() { + return e1() >= e2(); + }; + case "||": + return function() { + return e1() || e2(); + }; + default: + throw haxe_Exception.thrown("Unknown operation " + p1.p); + } + break; + case "-": + var e3 = this.makeExpr(l); + return function() { + return -e3(); + }; + } + throw haxe_Exception.thrown(p.p); + } + ,run: function(e) { + switch(e._hx_index) { + case 0: + var v = e.v; + var _this = this.buf; + var x = Std.string(this.resolve(v)); + _this.b += Std.string(x); + break; + case 1: + var e1 = e.expr; + var _this = this.buf; + var x = Std.string(e1()); + _this.b += Std.string(x); + break; + case 2: + var e1 = e.expr; + var eif = e.eif; + var eelse = e.eelse; + var v = e1(); + if(v == null || v == false) { + if(eelse != null) { + this.run(eelse); + } + } else { + this.run(eif); + } + break; + case 3: + var str = e.str; + this.buf.b += str == null ? "null" : "" + str; + break; + case 4: + var l = e.l; + var _g_head = l.h; + while(_g_head != null) { + var val = _g_head.item; + _g_head = _g_head.next; + var e1 = val; + this.run(e1); + } + break; + case 5: + var e1 = e.expr; + var loop = e.loop; + var v = e1(); + try { + var x = $getIterator(v); + if(x.hasNext == null) { + throw haxe_Exception.thrown(null); + } + v = x; + } catch( _g ) { + try { + if(v.hasNext == null) { + throw haxe_Exception.thrown(null); + } + } catch( _g1 ) { + throw haxe_Exception.thrown("Cannot iter on " + Std.string(v)); + } + } + this.stack.push(this.context); + var v1 = v; + var ctx = v1; + while(ctx.hasNext()) { + var ctx1 = ctx.next(); + this.context = ctx1; + this.run(loop); + } + this.context = this.stack.pop(); + break; + case 6: + var m = e.name; + var params = e.params; + var v = Reflect.field(this.macros,m); + var pl = []; + var old = this.buf; + pl.push($bind(this,this.resolve)); + var _g_head = params.h; + while(_g_head != null) { + var val = _g_head.item; + _g_head = _g_head.next; + var p = val; + if(p._hx_index == 0) { + var v1 = p.v; + pl.push(this.resolve(v1)); + } else { + this.buf = new StringBuf(); + this.run(p); + pl.push(this.buf.b); + } + } + this.buf = old; + try { + var _this = this.buf; + var x = Std.string(v.apply(this.macros,pl)); + _this.b += Std.string(x); + } catch( _g ) { + var e = haxe_Exception.caught(_g).unwrap(); + var plstr; + try { + plstr = pl.join(","); + } catch( _g1 ) { + plstr = "???"; + } + var msg = "Macro call " + m + "(" + plstr + ") failed (" + Std.string(e) + ")"; + throw haxe_Exception.thrown(msg); + } + break; + } + } +}; +var haxe_ValueException = function(value,previous,native) { + haxe_Exception.call(this,String(value),previous,native); + this.value = value; +}; +haxe_ValueException.__name__ = true; +haxe_ValueException.__super__ = haxe_Exception; +haxe_ValueException.prototype = $extend(haxe_Exception.prototype,{ + unwrap: function() { + return this.value; + } +}); +var haxe_ds_List = function() { + this.length = 0; +}; +haxe_ds_List.__name__ = true; +haxe_ds_List.prototype = { + add: function(item) { + var x = new haxe_ds__$List_ListNode(item,null); + if(this.h == null) { + this.h = x; + } else { + this.q.next = x; + } + this.q = x; + this.length++; + } + ,push: function(item) { + var x = new haxe_ds__$List_ListNode(item,this.h); + this.h = x; + if(this.q == null) { + this.q = x; + } + this.length++; + } + ,first: function() { + if(this.h == null) { + return null; + } else { + return this.h.item; + } + } + ,pop: function() { + if(this.h == null) { + return null; + } + var x = this.h.item; + this.h = this.h.next; + if(this.h == null) { + this.q = null; + } + this.length--; + return x; + } + ,isEmpty: function() { + return this.h == null; + } + ,toString: function() { + var s_b = ""; + var first = true; + var l = this.h; + s_b += "{"; + while(l != null) { + if(first) { + first = false; + } else { + s_b += ", "; + } + s_b += Std.string(Std.string(l.item)); + l = l.next; + } + s_b += "}"; + return s_b; + } +}; +var haxe_ds__$List_ListNode = function(item,next) { + this.item = item; + this.next = next; +}; +haxe_ds__$List_ListNode.__name__ = true; var js_Boot = function() { }; js_Boot.__name__ = true; js_Boot.__string_rec = function(o,s) { @@ -308,6 +994,34 @@ js_Boot.__string_rec = function(o,s) { case "function": return ""; case "object": + if(o.__enum__) { + var e = $hxEnums[o.__enum__]; + var con = e.__constructs__[o._hx_index]; + var n = con._hx_name; + if(con.__params__) { + s = s + "\t"; + return n + "(" + ((function($this) { + var $r; + var _g = []; + { + var _g1 = 0; + var _g2 = con.__params__; + while(true) { + if(!(_g1 < _g2.length)) { + break; + } + var p = _g2[_g1]; + _g1 = _g1 + 1; + _g.push(js_Boot.__string_rec(o[p],s)); + } + } + $r = _g; + return $r; + }(this))).join(",") + ")"; + } else { + return n; + } + } if(((o) instanceof Array)) { var str = "["; s += "\t"; @@ -492,26 +1206,32 @@ var xrfragment_Parser = $hx_exports["xrfragment"]["Parser"] = function() { }; xrfragment_Parser.__name__ = true; xrfragment_Parser.parse = function(key,value,store,index) { var Frag_h = Object.create(null); - Frag_h["#"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_PREDEFINED_VIEW | xrfragment_XRF.PV_EXECUTE; - Frag_h["src"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL; - Frag_h["href"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL | xrfragment_XRF.T_PREDEFINED_VIEW; - Frag_h["tag"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING; + Frag_h["#"] = xrfragment_XRF.IMMUTABLE | xrfragment_XRF.T_PREDEFINED_VIEW | xrfragment_XRF.PV_EXECUTE; + Frag_h["src"] = xrfragment_XRF.T_URL; + Frag_h["href"] = xrfragment_XRF.T_URL | xrfragment_XRF.T_PREDEFINED_VIEW; + Frag_h["tag"] = xrfragment_XRF.IMMUTABLE | xrfragment_XRF.T_STRING; Frag_h["pos"] = xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_VECTOR3 | xrfragment_XRF.T_STRING | xrfragment_XRF.METADATA | xrfragment_XRF.NAVIGATOR; Frag_h["rot"] = xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_VECTOR3 | xrfragment_XRF.METADATA | xrfragment_XRF.NAVIGATOR; - Frag_h["t"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_FLOAT | xrfragment_XRF.T_VECTOR2 | xrfragment_XRF.T_MEDIAFRAG | xrfragment_XRF.NAVIGATOR | xrfragment_XRF.METADATA; - Frag_h["xywh"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_FLOAT | xrfragment_XRF.T_VECTOR2 | xrfragment_XRF.T_MEDIAFRAG | xrfragment_XRF.NAVIGATOR | xrfragment_XRF.METADATA; - Frag_h["namespace"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING; - Frag_h["SPDX"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING; - Frag_h["unit"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING; - Frag_h["description"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING; - Frag_h["session"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.NAVIGATOR | xrfragment_XRF.METADATA | xrfragment_XRF.PROMPT; + Frag_h["t"] = xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_FLOAT | xrfragment_XRF.T_VECTOR2 | xrfragment_XRF.NAVIGATOR | xrfragment_XRF.METADATA; + Frag_h["s"] = xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_MEDIAFRAG; + Frag_h["loop"] = xrfragment_XRF.PV_OVERRIDE; + Frag_h["uv"] = xrfragment_XRF.T_VECTOR2 | xrfragment_XRF.T_MEDIAFRAG; + Frag_h["namespace"] = xrfragment_XRF.IMMUTABLE | xrfragment_XRF.T_STRING; + Frag_h["SPDX"] = xrfragment_XRF.IMMUTABLE | xrfragment_XRF.T_STRING; + Frag_h["unit"] = xrfragment_XRF.IMMUTABLE | xrfragment_XRF.T_STRING; + Frag_h["description"] = xrfragment_XRF.IMMUTABLE | xrfragment_XRF.T_STRING; var keyStripped = key.replace(xrfragment_XRF.operators.r,""); var isPVDynamic = key.length > 0 && !Object.prototype.hasOwnProperty.call(Frag_h,key); - var isPVDefault = value.length == 0 && key.length > 0 && key == "#"; if(isPVDynamic) { var v = new xrfragment_XRF(key,xrfragment_XRF.PV_EXECUTE | xrfragment_XRF.NAVIGATOR,index); v.validate(value); - v.flags = xrfragment_XRF.set(xrfragment_XRF.T_DYNAMIC,v.flags); + v.flags = xrfragment_XRF.set(xrfragment_XRF.T_DYNAMICKEY,v.flags); + if(!Object.prototype.hasOwnProperty.call(Frag_h,key)) { + v.flags = xrfragment_XRF.set(xrfragment_XRF.CUSTOMFRAG,v.flags); + } + if(value.length == 0) { + v.flags = xrfragment_XRF.set(xrfragment_XRF.T_DYNAMICKEYVALUE,v.flags); + } store[keyStripped] = v; return true; } @@ -529,7 +1249,7 @@ xrfragment_Parser.parse = function(key,value,store,index) { if(typeof(value) == "string") { v.guessType(v,value); } - v.noXRF = true; + v.flags = xrfragment_XRF.set(xrfragment_XRF.CUSTOMFRAG,v.flags); store[keyStripped] = v; } return true; @@ -552,8 +1272,12 @@ xrfragment_URI.parse = function(url,filter) { var key = splitByEqual[0]; var value = ""; if(splitByEqual.length > 1) { - var s = regexPlus.split(splitByEqual[1]).join(" "); - value = decodeURIComponent(s.split("+").join(" ")); + if(xrfragment_XRF.isVector.match(splitByEqual[1])) { + value = splitByEqual[1]; + } else { + var s = regexPlus.split(splitByEqual[1]).join(" "); + value = decodeURIComponent(s.split("+").join(" ")); + } } var ok = xrfragment_Parser.parse(key,value,store,i); } @@ -571,9 +1295,22 @@ xrfragment_URI.parse = function(url,filter) { } return store; }; +xrfragment_URI.template = function(uri,vars) { + var parts = uri.split("#"); + if(parts.length == 1) { + return uri; + } + var frag = parts[1]; + frag = StringTools.replace(frag,"{","::"); + frag = StringTools.replace(frag,"}","::"); + frag = new haxe_Template(frag).execute(vars); + frag = StringTools.replace(frag,"null",""); + parts[1] = frag; + return parts.join("#"); +}; var xrfragment_XRF = $hx_exports["xrfragment"]["XRF"] = function(_fragment,_flags,_index) { - this.speed = []; this.floats = []; + this.shift = []; this.fragment = _fragment; this.flags = _flags; this.index = _index; @@ -606,10 +1343,21 @@ xrfragment_XRF.prototype = { } ,guessType: function(v,str) { v.string = str; + if(xrfragment_XRF.isReset.match(v.fragment)) { + v.reset = true; + } + if(v.fragment == "loop") { + v.loop = true; + } if(typeof(str) != "string") { return; } if(str.length > 0) { + if(xrfragment_XRF.isXRFScheme.match(str)) { + v.xrfScheme = true; + str = str.replace(xrfragment_XRF.isXRFScheme.r,""); + v.string = str; + } if(str.split(",").length > 1) { var xyzn = str.split(","); if(xyzn.length > 0) { @@ -625,7 +1373,8 @@ xrfragment_XRF.prototype = { var _g1 = xyzn.length; while(_g < _g1) { var i = _g++; - v.floats.push(parseFloat(xyzn[i])); + v.shift.push(xrfragment_XRF.isShift.match(xyzn[i])); + v.floats.push(parseFloat(xyzn[i].replace(xrfragment_XRF.isShift.r,""))); } } if(xrfragment_XRF.isColor.match(str)) { @@ -638,19 +1387,7 @@ xrfragment_XRF.prototype = { if(xrfragment_XRF.isInt.match(str)) { v.int = Std.parseInt(str); v.x = v.int; - } - if(xrfragment_XRF.isMediaFrag.match(str)) { - var speed = str.split("*"); - v.speed = []; - if(speed.length > 1) { - var values = speed[1].split(","); - var _g = 0; - var _g1 = values.length; - while(_g < _g1) { - var i = _g++; - v.speed.push(parseFloat(values[i])); - } - } + v.floats.push(v.x); } v.filter = new xrfragment_Filter(v.fragment + "=" + v.string); } else { @@ -658,20 +1395,32 @@ xrfragment_XRF.prototype = { } } }; +function $getIterator(o) { if( o instanceof Array ) return new haxe_iterators_ArrayIterator(o); else return o.iterator(); } +function $bind(o,m) { if( m == null ) return null; if( m.__id__ == null ) m.__id__ = $global.$haxeUID++; var f; if( o.hx__closures__ == null ) o.hx__closures__ = {}; else f = o.hx__closures__[m.__id__]; if( f == null ) { f = m.bind(o); o.hx__closures__[m.__id__] = f; } return f; } +$global.$haxeUID |= 0; if(typeof(performance) != "undefined" ? typeof(performance.now) == "function" : false) { HxOverrides.now = performance.now.bind(performance); } +if( String.fromCodePoint == null ) String.fromCodePoint = function(c) { return c < 0x10000 ? String.fromCharCode(c) : String.fromCharCode((c>>10)+0xD7C0)+String.fromCharCode((c&0x3FF)+0xDC00); } String.__name__ = true; Array.__name__ = true; js_Boot.__toStr = ({ }).toString; Test.errors = 0; +haxe_Template.splitter = new EReg("(::[A-Za-z0-9_ ()&|!+=/><*.\"-]+::|\\$\\$([A-Za-z0-9_-]+)\\()",""); +haxe_Template.expr_splitter = new EReg("(\\(|\\)|[ \r\n\t]*\"[^\"]*\"[ \r\n\t]*|[!+=/><*.&|-]+)",""); +haxe_Template.expr_trim = new EReg("^[ ]*([^ ]+)[ ]*$",""); +haxe_Template.expr_int = new EReg("^[0-9]+$",""); +haxe_Template.expr_float = new EReg("^([+-]?)(?=\\d|,\\d)\\d*(,\\d*)?([Ee]([+-]?\\d+))?$",""); +haxe_Template.globals = { }; +haxe_Template.hxKeepArrayIterator = new haxe_iterators_ArrayIterator([]); xrfragment_Parser.error = ""; xrfragment_Parser.debug = false; -xrfragment_XRF.ASSET = 1; +xrfragment_URI.__meta__ = { statics : { template : { keep : null}}}; +xrfragment_XRF.IMMUTABLE = 1; xrfragment_XRF.PROP_BIND = 2; xrfragment_XRF.QUERY_OPERATOR = 4; xrfragment_XRF.PROMPT = 8; -xrfragment_XRF.ROUNDROBIN = 16; +xrfragment_XRF.CUSTOMFRAG = 16; xrfragment_XRF.NAVIGATOR = 32; xrfragment_XRF.METADATA = 64; xrfragment_XRF.PV_OVERRIDE = 128; @@ -685,7 +1434,8 @@ xrfragment_XRF.T_URL = 262144; xrfragment_XRF.T_PREDEFINED_VIEW = 524288; xrfragment_XRF.T_STRING = 1048576; xrfragment_XRF.T_MEDIAFRAG = 2097152; -xrfragment_XRF.T_DYNAMIC = 4194304; +xrfragment_XRF.T_DYNAMICKEY = 4194304; +xrfragment_XRF.T_DYNAMICKEYVALUE = 8388608; xrfragment_XRF.isColor = new EReg("^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$",""); xrfragment_XRF.isInt = new EReg("^[-0-9]+$",""); xrfragment_XRF.isFloat = new EReg("^[-0-9]+\\.[0-9]+$",""); @@ -693,12 +1443,15 @@ xrfragment_XRF.isVector = new EReg("([,]+|\\w)",""); xrfragment_XRF.isUrl = new EReg("(://)?\\..*",""); xrfragment_XRF.isUrlOrPretypedView = new EReg("(^#|://)?\\..*",""); xrfragment_XRF.isString = new EReg(".*",""); -xrfragment_XRF.operators = new EReg("(^-|[\\*]+)",""); +xrfragment_XRF.operators = new EReg("(^[-]|^[!]|[\\*]$)","g"); xrfragment_XRF.isProp = new EReg("^.*=[><=]?",""); xrfragment_XRF.isExclude = new EReg("^-",""); xrfragment_XRF.isDeep = new EReg("\\*",""); xrfragment_XRF.isNumber = new EReg("^[0-9\\.]+$",""); -xrfragment_XRF.isMediaFrag = new EReg("^[0-9\\.,\\*]+$",""); +xrfragment_XRF.isMediaFrag = new EReg("^([0-9\\.,\\*+-]+)$",""); +xrfragment_XRF.isReset = new EReg("^!",""); +xrfragment_XRF.isShift = new EReg("^(\\+|--)",""); +xrfragment_XRF.isXRFScheme = new EReg("^xrf://",""); Test.main(); -})({}); +})(typeof window != "undefined" ? window : typeof global != "undefined" ? global : typeof self != "undefined" ? self : this); var xrfragment = $hx_exports["xrfragment"]; diff --git a/test/generated/test.py b/test/generated/test.py index 6ee835a..928eb2a 100644 --- a/test/generated/test.py +++ b/test/generated/test.py @@ -3,10 +3,11 @@ import sys import math as python_lib_Math import math as Math import inspect as python_lib_Inspect +import re as python_lib_Re import sys as python_lib_Sys import functools as python_lib_Functools -import re as python_lib_Re import traceback as python_lib_Traceback +from io import StringIO as python_lib_io_StringIO import urllib.parse as python_lib_urllib_Parse @@ -54,6 +55,7 @@ class Enum: else: return self.tag + '(' + (', '.join(str(v) for v in self.params)) + ')' +Enum._hx_class = Enum class Class: pass @@ -130,17 +132,53 @@ class EReg: replace = _hx_local_0 return python_lib_Re.sub(self.pattern,replace,s,(0 if (self._hx_global) else 1)) +EReg._hx_class = EReg class Reflect: _hx_class_name = "Reflect" __slots__ = () - _hx_statics = ["field", "deleteField", "copy"] + _hx_statics = ["field", "getProperty", "callMethod", "isObject", "deleteField", "copy"] @staticmethod def field(o,field): return python_Boot.field(o,field) + @staticmethod + def getProperty(o,field): + if (o is None): + return None + if (field in python_Boot.keywords): + field = ("_hx_" + field) + elif ((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95))): + field = ("_hx_" + field) + if isinstance(o,_hx_AnonObject): + return Reflect.field(o,field) + tmp = Reflect.field(o,("get_" + ("null" if field is None else field))) + if ((tmp is not None) and callable(tmp)): + return tmp() + else: + return Reflect.field(o,field) + + @staticmethod + def callMethod(o,func,args): + if callable(func): + return func(*args) + else: + return None + + @staticmethod + def isObject(v): + _g = Type.typeof(v) + tmp = _g.index + if (tmp == 4): + return True + elif (tmp == 6): + _g1 = _g.params[0] + return True + else: + return False + @staticmethod def deleteField(o,field): if (field in python_Boot.keywords): @@ -165,6 +203,7 @@ class Reflect: value = Reflect.field(o,f) setattr(o2,(("_hx_" + f) if ((f in python_Boot.keywords)) else (("_hx_" + f) if (((((len(f) > 2) and ((ord(f[0]) == 95))) and ((ord(f[1]) == 95))) and ((ord(f[(len(f) - 1)]) != 95)))) else f)),value) return o2 +Reflect._hx_class = Reflect class Std: @@ -359,6 +398,7 @@ class Std: if (r1 != x): return Std.parseFloat(r1) return Math.NaN +Std._hx_class = Std class Float: pass @@ -373,10 +413,21 @@ class Bool: pass class Dynamic: pass +class StringBuf: + _hx_class_name = "StringBuf" + __slots__ = ("b",) + _hx_fields = ["b"] + + def __init__(self): + self.b = python_lib_io_StringIO() + +StringBuf._hx_class = StringBuf + + class StringTools: _hx_class_name = "StringTools" __slots__ = () - _hx_statics = ["isSpace", "ltrim", "rtrim", "trim"] + _hx_statics = ["isSpace", "ltrim", "rtrim", "trim", "replace"] @staticmethod def isSpace(s,pos): @@ -414,25 +465,32 @@ class StringTools: def trim(s): return StringTools.ltrim(StringTools.rtrim(s)) + @staticmethod + def replace(s,sub,by): + _this = (list(s) if ((sub == "")) else s.split(sub)) + return by.join([python_Boot.toString1(x1,'') for x1 in _this]) +StringTools._hx_class = StringTools + class Test: _hx_class_name = "Test" __slots__ = () - _hx_statics = ["errors", "main", "test", "equalX", "equalXY", "equalXYZ", "equalMediaFragment", "equalMediaFragmentSpd"] + _hx_statics = ["errors", "main", "test", "equalX", "equalXY", "equalXYZ", "equalMediaFragment"] @staticmethod def main(): Test.test("url.json",[_hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testPredefinedView", 'input': "mypredefinedview", 'out': True}), 'label': "test predefined view executed", 'data': "http://foo.com?foo=1#mypredefinedview"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testPredefinedView", 'input': "another", 'out': True}), 'label': "test predefined view executed (multiple)", 'data': "http://foo.com?foo=1#mypredefinedview&another"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testPredefinedView", 'input': "mypredefinedview", 'out': True}), 'label': "test predefined view executed (multiple)", 'data': "http://foo.com?foo=1#mypredefinedview&another"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testParsed", 'input': "mycustom", 'out': True}), 'label': "test custom property", 'data': "http://foo.com?foo=1#mycustom=foo"})]) Test.test("pos.json",[_hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.string", 'input': "pos", 'out': "1.2,2.2"}), 'label': "equal.string", 'data': "http://foo.com?foo=1#pos=1.2,2.2"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.xyz", 'input': "pos", 'out': "1.2,2.2,3"}), 'label': "equal.xyz", 'data': "http://foo.com?foo=1#pos=1.2,2.2,3"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.xyz", 'input': "pos", 'out': "1,2,3"}), 'label': "pos equal.xyz", 'data': "http://foo.com?foo=1#pos=1,2,3"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.string", 'input': "pos", 'out': "world2"}), 'label': "pos equal.xyz", 'data': "http://foo.com?foo=1#pos=world2"})]) - Test.test("t.json",[_hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.x", 'input': "t", 'out': "1"}), 'label': "a equal.x", 'data': "http://foo.com?foo=1#t=1"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.x", 'input': "t", 'out': "-1"}), 'label': "a equal.x", 'data': "http://foo.com?foo=1#t=-1"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.x", 'input': "t", 'out': "-1.02"}), 'label': "a equal.x", 'data': "http://foo.com?foo=1#t=-1.02"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.xy", 'input': "t", 'out': "1,2"}), 'label': "a equal.xy", 'data': "http://foo.com?foo=1#t=1,2,3"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.xyz", 'input': "t", 'out': "1,2,3"}), 'label': "a equal.xyz", 'data': "http://foo.com?foo=1#t=1,2,3"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.xyz", 'input': "t", 'out': "1,-2,3"}), 'label': "a equal.xyz", 'data': "http://foo.com?foo=1#t=1,-2,3"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.xy", 'input': "t", 'out': "1,100"}), 'label': "a equal.xy", 'data': "http://foo.com?foo=1#t=1,100"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testBrowserOverride", 'input': "t", 'out': True}), 'label': "browser URI can override t (defined in asset)", 'data': "http://foo.com?foo=1#t=2,500"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.mediafragmentT", 'input': "3", 'out': "500"}), 'label': "a equal.mediafragment", 'data': "http://foo.com?foo=1#t=1,100,400,500*1.2,2.3"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.mediafragmentTSpd", 'input': "1", 'out': "2.3"}), 'label': "a equal.mediafragmentSpeed", 'data': "http://foo.com?foo=1#t=1,100,400,500*1.2,2.3"})]) - Test.test("xywh.json",[_hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.mediafragmentXYWH", 'input': "2", 'out': "1"}), 'label': "xywh", 'data': "http://foo.com?foo=1#xywh=0,0,1,1"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.mediafragmentXYWH", 'input': "3", 'out': "500"}), 'label': "a equal.mediafragment", 'data': "http://foo.com?foo=1#xywh=1,100,400,500*1.2,2.3"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.mediafragmentXYWHSpd", 'input': "1", 'out': "2.3"}), 'label': "a equal.mediafragmentSpeed", 'data': "http://foo.com?foo=1#xywh=1,100,400,500*1.2,2.3"})]) - Test.test("filter.selectors.json",[_hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testParsed", 'input': "myid", 'out': True}), 'label': "myid exists", 'data': "http://foo.com?foo=1#foo*&-sometag&-someid&myid"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testParsed", 'input': "tag", 'out': True}), 'label': "tag exists", 'data': "http://foo.com?foo=1#tag=bar"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testParsed", 'input': "tag", 'out': True}), 'label': "tag exists", 'data': "http://foo.com?foo=1#-tag=bar"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testParsed", 'input': "price", 'out': True}), 'label': "filter test", 'data': "http://foo.com?foo=1#price=>2"}), _hx_AnonObject({'fn': "filter", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["tag", "bar"], 'out': True}), 'data': "tag=bar"}), _hx_AnonObject({'fn': "filter", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["tag", "foo"], 'out': False}), 'data': "-tag=foo"}), _hx_AnonObject({'fn': "filter", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["tag", "foo"], 'out': False}), 'data': "-tag*=foo"}), _hx_AnonObject({'fn': "filter", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["tag", "3"], 'out': False}), 'data': "-tag=>2"}), _hx_AnonObject({'fn': "filter", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["price", "1"], 'out': False}), 'data': "price=>2"}), _hx_AnonObject({'fn': "filter", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["price", "5"], 'out': False}), 'data': "price=<2"}), _hx_AnonObject({'fn': "filter", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["price", "1"], 'out': True}), 'data': "price=<2"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testFilterDeep", 'input': ["foo"], 'out': 1}), 'label': "foo should be deep", 'data': "#foo*"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testFilterDeep", 'input': ["foo"], 'out': 2}), 'label': "foo should be deep incl. embeds", 'data': "#foo**"})]) + Test.test("t.json",[_hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.x", 'input': "t", 'out': "1"}), 'label': "a equal.x", 'data': "http://foo.com?foo=1#t=1"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.x", 'input': "t", 'out': "-1"}), 'label': "a equal.x", 'data': "http://foo.com?foo=1#t=-1"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.x", 'input': "t", 'out': "-1.02"}), 'label': "a equal.x", 'data': "http://foo.com?foo=1#t=-1.02"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.xy", 'input': "t", 'out': "1,2"}), 'label': "a equal.xy", 'data': "http://foo.com?foo=1#t=1,2,3"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.xyz", 'input': "t", 'out': "1,2,3"}), 'label': "a equal.xyz", 'data': "http://foo.com?foo=1#t=1,2,3"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.xyz", 'input': "t", 'out': "1,-2,3"}), 'label': "a equal.xyz", 'data': "http://foo.com?foo=1#t=1,-2,3"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.xy", 'input': "t", 'out': "1,100"}), 'label': "a equal.xy", 'data': "http://foo.com?foo=1#t=1,100"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testBrowserOverride", 'input': "t", 'out': True}), 'label': "browser URI can override t (defined in asset)", 'data': "http://foo.com?foo=1#t=2,500"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.mediafragmentT", 'input': "3", 'out': "500"}), 'label': "a equal.mediafragment", 'data': "http://foo.com?foo=1#t=1,100,400,500"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.mediafragmentT", 'input': "3", 'out': "500"}), 'label': "a equal.mediafragment loop", 'data': "http://foo.com?foo=1#t=l:1,100,400,500"})]) + Test.test("s.json",[_hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.x", 'input': "s", 'out': "1"}), 'label': "playback speed", 'data': "http://foo.com?foo=1#s=1"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.x", 'input': "s", 'out': "0.5"}), 'label': "playback speed", 'data': "http://foo.com?foo=1#s=0.5"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.x", 'input': "s", 'out': "-0.5"}), 'label': "playback speed", 'data': "http://foo.com?foo=1#s=-0.5"})]) + Test.test("uv.json",[_hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.xy", 'input': "uv", 'out': "1.2,2.2"}), 'label': "equal.string uv", 'data': "http://foo.com?foo=1#uv=1.2,2.2"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.xyz", 'input': "uv", 'out': "1.2,2.2,1"}), 'label': "equal.string uv", 'data': "http://foo.com?foo=1#uv=1.2,2.2,+1,+1"})]) + Test.test("filter.selectors.json",[_hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testParsed", 'input': "myid", 'out': True}), 'label': "myid exists", 'data': "http://foo.com?foo=1#foo*&-sometag&-someid&myid"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testParsed", 'input': "tag", 'out': True}), 'label': "tag exists", 'data': "http://foo.com?foo=1#tag=bar"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testParsed", 'input': "tag", 'out': True}), 'label': "tag exists", 'data': "http://foo.com?foo=1#-tag=bar"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testParsed", 'input': "price", 'out': True}), 'label': "filter test", 'data': "http://foo.com?foo=1#price=>2"}), _hx_AnonObject({'fn': "filter", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["tag", "bar"], 'out': True}), 'data': "tag=bar"}), _hx_AnonObject({'fn': "filter", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["tag", "foo"], 'out': False}), 'data': "-tag=foo"}), _hx_AnonObject({'fn': "filter", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["tag", "foo"], 'out': False}), 'data': "-tag*=foo"}), _hx_AnonObject({'fn': "filter", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["tag", "3"], 'out': False}), 'data': "-tag=>2"}), _hx_AnonObject({'fn': "filter", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["price", "1"], 'out': False}), 'data': "price=>2"}), _hx_AnonObject({'fn': "filter", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["price", "5"], 'out': False}), 'data': "price=<2"}), _hx_AnonObject({'fn': "filter", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["price", "1"], 'out': True}), 'data': "price=<2"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testFilterDeep", 'input': ["foo"], 'out': 1}), 'label': "foo should be deep", 'data': "#foo*"})]) if (Test.errors > 1): print(str((("\n-----\n[ ❌] " + Std.string(Test.errors)) + " errors :/"))) @staticmethod def test(topic,spec): - print(str(("\n[.] running " + ("null" if topic is None else topic)))) + print(str(("\n[ . ] running " + ("null" if topic is None else topic)))) Filter = xrfragment_Filter _g = 0 _g1 = len(spec) @@ -473,12 +531,10 @@ class Test: valid = Test.equalXYZ(res,item) if (Reflect.field(Reflect.field(item,"expect"),"fn") == "equal.mediafragmentT"): valid = Test.equalMediaFragment(res,item,"t") - if (Reflect.field(Reflect.field(item,"expect"),"fn") == "equal.mediafragmentXYWH"): - valid = Test.equalMediaFragment(res,item,"xywh") - if (Reflect.field(Reflect.field(item,"expect"),"fn") == "equal.mediafragmentTSpd"): - valid = Test.equalMediaFragmentSpd(res,item,"t") - if (Reflect.field(Reflect.field(item,"expect"),"fn") == "equal.mediafragmentXYWHSpd"): - valid = Test.equalMediaFragmentSpd(res,item,"xywh") + if (Reflect.field(Reflect.field(item,"expect"),"fn") == "equal.mediafragmentUV"): + valid = Test.equalMediaFragment(res,item,"uv") + if (Reflect.field(Reflect.field(item,"expect"),"fn") == "equal.mediafragmentS"): + valid = Test.equalMediaFragment(res,item,"s") if (Reflect.field(Reflect.field(item,"expect"),"fn") == "testFilterRoot"): valid = (python_Boot.hasField(res,HxOverrides.arrayGet(Reflect.field(Reflect.field(item,"expect"),"input"), 0)) and (HxOverrides.eq(Reflect.field(Reflect.field(Reflect.field(Reflect.field(res,HxOverrides.arrayGet(Reflect.field(Reflect.field(item,"expect"),"input"), 0)),"filter"),"get")(),"root"),Reflect.field(Reflect.field(item,"expect"),"out")))) if (Reflect.field(Reflect.field(item,"expect"),"fn") == "testFilterDeep"): @@ -523,27 +579,75 @@ class Test: if ((not Reflect.field(Reflect.field(item,"expect"),"out")) and (not Reflect.field(res,Reflect.field(Reflect.field(item,"expect"),"input")))): return True else: - return (HxOverrides.arrayGet(Reflect.field(Reflect.field(res,key),"floats"), Std.parseInt(Reflect.field(Reflect.field(item,"expect"),"input"))) == Std.parseInt(Reflect.field(Reflect.field(item,"expect"),"out"))) + return (HxOverrides.arrayGet(Reflect.field(Reflect.field(res,key),"floats"), Std.parseInt(Reflect.field(Reflect.field(item,"expect"),"input"))) == Std.parseFloat(Reflect.field(Reflect.field(item,"expect"),"out"))) +Test._hx_class = Test + +class ValueType(Enum): + __slots__ = () + _hx_class_name = "ValueType" + _hx_constructs = ["TNull", "TInt", "TFloat", "TBool", "TObject", "TFunction", "TClass", "TEnum", "TUnknown"] @staticmethod - def equalMediaFragmentSpd(res,item,key): - if ((not Reflect.field(Reflect.field(item,"expect"),"out")) and (not Reflect.field(res,Reflect.field(Reflect.field(item,"expect"),"input")))): - return True + def TClass(c): + return ValueType("TClass", 6, (c,)) + + @staticmethod + def TEnum(e): + return ValueType("TEnum", 7, (e,)) +ValueType.TNull = ValueType("TNull", 0, ()) +ValueType.TInt = ValueType("TInt", 1, ()) +ValueType.TFloat = ValueType("TFloat", 2, ()) +ValueType.TBool = ValueType("TBool", 3, ()) +ValueType.TObject = ValueType("TObject", 4, ()) +ValueType.TFunction = ValueType("TFunction", 5, ()) +ValueType.TUnknown = ValueType("TUnknown", 8, ()) +ValueType._hx_class = ValueType + + +class Type: + _hx_class_name = "Type" + __slots__ = () + _hx_statics = ["typeof"] + + @staticmethod + def typeof(v): + if (v is None): + return ValueType.TNull + elif isinstance(v,bool): + return ValueType.TBool + elif isinstance(v,int): + return ValueType.TInt + elif isinstance(v,float): + return ValueType.TFloat + elif isinstance(v,str): + return ValueType.TClass(str) + elif isinstance(v,list): + return ValueType.TClass(list) + elif (isinstance(v,_hx_AnonObject) or python_lib_Inspect.isclass(v)): + return ValueType.TObject + elif isinstance(v,Enum): + return ValueType.TEnum(v.__class__) + elif (isinstance(v,type) or hasattr(v,"_hx_class")): + return ValueType.TClass(v.__class__) + elif callable(v): + return ValueType.TFunction else: - return (HxOverrides.arrayGet(Reflect.field(Reflect.field(res,key),"speed"), Std.parseInt(Reflect.field(Reflect.field(item,"expect"),"input"))) == Std.parseFloat(Reflect.field(Reflect.field(item,"expect"),"out"))) + return ValueType.TUnknown +Type._hx_class = Type class haxe_IMap: _hx_class_name = "haxe.IMap" __slots__ = () +haxe_IMap._hx_class = haxe_IMap class haxe_Exception(Exception): _hx_class_name = "haxe.Exception" - __slots__ = ("_hx___nativeStack", "_hx___nativeException", "_hx___previousException") - _hx_fields = ["__nativeStack", "__nativeException", "__previousException"] - _hx_methods = ["unwrap"] - _hx_statics = ["caught"] + __slots__ = ("_hx___nativeStack", "_hx___skipStack", "_hx___nativeException", "_hx___previousException") + _hx_fields = ["__nativeStack", "__skipStack", "__nativeException", "__previousException"] + _hx_methods = ["unwrap", "get_native"] + _hx_statics = ["caught", "thrown"] _hx_interfaces = [] _hx_super = Exception @@ -552,6 +656,7 @@ class haxe_Exception(Exception): self._hx___previousException = None self._hx___nativeException = None self._hx___nativeStack = None + self._hx___skipStack = 0 super().__init__(message) self._hx___previousException = previous if ((native is not None) and Std.isOfType(native,BaseException)): @@ -568,6 +673,9 @@ class haxe_Exception(Exception): def unwrap(self): return self._hx___nativeException + def get_native(self): + return self._hx___nativeException + @staticmethod def caught(value): if Std.isOfType(value,haxe_Exception): @@ -577,6 +685,18 @@ class haxe_Exception(Exception): else: return haxe_ValueException(value,None,value) + @staticmethod + def thrown(value): + if Std.isOfType(value,haxe_Exception): + return value.get_native() + elif Std.isOfType(value,BaseException): + return value + else: + e = haxe_ValueException(value) + e._hx___skipStack = (e._hx___skipStack + 1) + return e + +haxe_Exception._hx_class = haxe_Exception class haxe_NativeStackTrace: @@ -597,37 +717,41 @@ class haxe_NativeStackTrace: return infos else: return [] +haxe_NativeStackTrace._hx_class = haxe_NativeStackTrace +class haxe__Template_TemplateExpr(Enum): + __slots__ = () + _hx_class_name = "haxe._Template.TemplateExpr" + _hx_constructs = ["OpVar", "OpExpr", "OpIf", "OpStr", "OpBlock", "OpForeach", "OpMacro"] -class haxe_ValueException(haxe_Exception): - _hx_class_name = "haxe.ValueException" - __slots__ = ("value",) - _hx_fields = ["value"] - _hx_methods = ["unwrap"] - _hx_statics = [] - _hx_interfaces = [] - _hx_super = haxe_Exception + @staticmethod + def OpVar(v): + return haxe__Template_TemplateExpr("OpVar", 0, (v,)) + @staticmethod + def OpExpr(expr): + return haxe__Template_TemplateExpr("OpExpr", 1, (expr,)) - def __init__(self,value,previous = None,native = None): - self.value = None - super().__init__(Std.string(value),previous,native) - self.value = value + @staticmethod + def OpIf(expr,eif,eelse): + return haxe__Template_TemplateExpr("OpIf", 2, (expr,eif,eelse)) - def unwrap(self): - return self.value + @staticmethod + def OpStr(str): + return haxe__Template_TemplateExpr("OpStr", 3, (str,)) + @staticmethod + def OpBlock(l): + return haxe__Template_TemplateExpr("OpBlock", 4, (l,)) + @staticmethod + def OpForeach(expr,loop): + return haxe__Template_TemplateExpr("OpForeach", 5, (expr,loop)) -class haxe_ds_StringMap: - _hx_class_name = "haxe.ds.StringMap" - __slots__ = ("h",) - _hx_fields = ["h"] - _hx_interfaces = [haxe_IMap] - - def __init__(self): - self.h = dict() - + @staticmethod + def OpMacro(name,params): + return haxe__Template_TemplateExpr("OpMacro", 6, (name,params)) +haxe__Template_TemplateExpr._hx_class = haxe__Template_TemplateExpr class haxe_iterators_ArrayIterator: @@ -653,6 +777,613 @@ class haxe_iterators_ArrayIterator: return python_internal_ArrayImpl._get(self.array, _hx_local_2()) return _hx_local_3() +haxe_iterators_ArrayIterator._hx_class = haxe_iterators_ArrayIterator + + +class haxe_Template: + _hx_class_name = "haxe.Template" + __slots__ = ("expr", "context", "macros", "stack", "buf") + _hx_fields = ["expr", "context", "macros", "stack", "buf"] + _hx_methods = ["execute", "resolve", "parseTokens", "parseBlock", "parse", "parseExpr", "makeConst", "makePath", "makeExpr", "skipSpaces", "makeExpr2", "run"] + _hx_statics = ["splitter", "expr_splitter", "expr_trim", "expr_int", "expr_float", "globals", "hxKeepArrayIterator"] + + def __init__(self,_hx_str): + self.buf = None + self.stack = None + self.macros = None + self.context = None + self.expr = None + tokens = self.parseTokens(_hx_str) + self.expr = self.parseBlock(tokens) + if (not tokens.isEmpty()): + raise haxe_Exception.thrown((("Unexpected '" + Std.string(tokens.first().s)) + "'")) + + def execute(self,context,macros = None): + self.macros = (_hx_AnonObject({}) if ((macros is None)) else macros) + self.context = context + self.stack = haxe_ds_List() + self.buf = StringBuf() + self.run(self.expr) + return self.buf.b.getvalue() + + def resolve(self,v): + if (v == "__current__"): + return self.context + if Reflect.isObject(self.context): + value = Reflect.getProperty(self.context,v) + if ((value is not None) or python_Boot.hasField(self.context,v)): + return value + _g_head = self.stack.h + while (_g_head is not None): + val = _g_head.item + _g_head = _g_head.next + ctx = val + value = Reflect.getProperty(ctx,v) + if ((value is not None) or python_Boot.hasField(ctx,v)): + return value + return Reflect.field(haxe_Template.globals,v) + + def parseTokens(self,data): + tokens = haxe_ds_List() + while True: + _this = haxe_Template.splitter + _this.matchObj = python_lib_Re.search(_this.pattern,data) + if (not ((_this.matchObj is not None))): + break + _this1 = haxe_Template.splitter + p_pos = _this1.matchObj.start() + p_len = (_this1.matchObj.end() - _this1.matchObj.start()) + if (p_pos > 0): + tokens.add(_hx_AnonObject({'p': HxString.substr(data,0,p_pos), 's': True, 'l': None})) + if (HxString.charCodeAt(data,p_pos) == 58): + tokens.add(_hx_AnonObject({'p': HxString.substr(data,(p_pos + 2),(p_len - 4)), 's': False, 'l': None})) + _this2 = haxe_Template.splitter + data = HxString.substr(_this2.matchObj.string,_this2.matchObj.end(),None) + continue + parp = (p_pos + p_len) + npar = 1 + params = [] + part = "" + while True: + c = HxString.charCodeAt(data,parp) + parp = (parp + 1) + if (c == 40): + npar = (npar + 1) + elif (c == 41): + npar = (npar - 1) + if (npar <= 0): + break + elif (c is None): + raise haxe_Exception.thrown("Unclosed macro parenthesis") + if ((c == 44) and ((npar == 1))): + params.append(part) + part = "" + else: + part = (("null" if part is None else part) + HxOverrides.stringOrNull("".join(map(chr,[c])))) + params.append(part) + tokens.add(_hx_AnonObject({'p': haxe_Template.splitter.matchObj.group(2), 's': False, 'l': params})) + data = HxString.substr(data,parp,(len(data) - parp)) + if (len(data) > 0): + tokens.add(_hx_AnonObject({'p': data, 's': True, 'l': None})) + return tokens + + def parseBlock(self,tokens): + l = haxe_ds_List() + while True: + t = tokens.first() + if (t is None): + break + if ((not t.s) and ((((t.p == "end") or ((t.p == "else"))) or ((HxString.substr(t.p,0,7) == "elseif "))))): + break + l.add(self.parse(tokens)) + if (l.length == 1): + return l.first() + return haxe__Template_TemplateExpr.OpBlock(l) + + def parse(self,tokens): + t = tokens.pop() + p = t.p + if t.s: + return haxe__Template_TemplateExpr.OpStr(p) + if (t.l is not None): + pe = haxe_ds_List() + _g = 0 + _g1 = t.l + while (_g < len(_g1)): + p1 = (_g1[_g] if _g >= 0 and _g < len(_g1) else None) + _g = (_g + 1) + pe.add(self.parseBlock(self.parseTokens(p1))) + return haxe__Template_TemplateExpr.OpMacro(p,pe) + def _hx_local_2(kwd): + pos = -1 + length = len(kwd) + if (HxString.substr(p,0,length) == kwd): + pos = length + _g_offset = 0 + _g_s = HxString.substr(p,length,None) + while (_g_offset < len(_g_s)): + index = _g_offset + _g_offset = (_g_offset + 1) + c = ord(_g_s[index]) + if (c == 32): + pos = (pos + 1) + else: + break + return pos + kwdEnd = _hx_local_2 + pos = kwdEnd("if") + if (pos > 0): + p = HxString.substr(p,pos,(len(p) - pos)) + e = self.parseExpr(p) + eif = self.parseBlock(tokens) + t = tokens.first() + eelse = None + if (t is None): + raise haxe_Exception.thrown("Unclosed 'if'") + if (t.p == "end"): + tokens.pop() + eelse = None + elif (t.p == "else"): + tokens.pop() + eelse = self.parseBlock(tokens) + t = tokens.pop() + if ((t is None) or ((t.p != "end"))): + raise haxe_Exception.thrown("Unclosed 'else'") + else: + t.p = HxString.substr(t.p,4,(len(t.p) - 4)) + eelse = self.parse(tokens) + return haxe__Template_TemplateExpr.OpIf(e,eif,eelse) + pos = kwdEnd("foreach") + if (pos >= 0): + p = HxString.substr(p,pos,(len(p) - pos)) + e = self.parseExpr(p) + efor = self.parseBlock(tokens) + t = tokens.pop() + if ((t is None) or ((t.p != "end"))): + raise haxe_Exception.thrown("Unclosed 'foreach'") + return haxe__Template_TemplateExpr.OpForeach(e,efor) + _this = haxe_Template.expr_splitter + _this.matchObj = python_lib_Re.search(_this.pattern,p) + if (_this.matchObj is not None): + return haxe__Template_TemplateExpr.OpExpr(self.parseExpr(p)) + return haxe__Template_TemplateExpr.OpVar(p) + + def parseExpr(self,data): + l = haxe_ds_List() + expr = data + while True: + _this = haxe_Template.expr_splitter + _this.matchObj = python_lib_Re.search(_this.pattern,data) + if (not ((_this.matchObj is not None))): + break + _this1 = haxe_Template.expr_splitter + p_pos = _this1.matchObj.start() + p_len = (_this1.matchObj.end() - _this1.matchObj.start()) + k = (p_pos + p_len) + if (p_pos != 0): + l.add(_hx_AnonObject({'p': HxString.substr(data,0,p_pos), 's': True})) + p = haxe_Template.expr_splitter.matchObj.group(0) + startIndex = None + l.add(_hx_AnonObject({'p': p, 's': (((p.find("\"") if ((startIndex is None)) else HxString.indexOfImpl(p,"\"",startIndex))) >= 0)})) + _this2 = haxe_Template.expr_splitter + data = HxString.substr(_this2.matchObj.string,_this2.matchObj.end(),None) + if (len(data) != 0): + _g_offset = 0 + _g_s = data + while (_g_offset < len(_g_s)): + _g1_key = _g_offset + s = _g_s + index = _g_offset + _g_offset = (_g_offset + 1) + _g1_value = (-1 if ((index >= len(s))) else ord(s[index])) + i = _g1_key + c = _g1_value + if (c != 32): + l.add(_hx_AnonObject({'p': HxString.substr(data,i,None), 's': True})) + break + e = None + try: + e = self.makeExpr(l) + if (not l.isEmpty()): + raise haxe_Exception.thrown(l.first().p) + except BaseException as _g: + None + _g1 = haxe_Exception.caught(_g).unwrap() + if Std.isOfType(_g1,str): + s = _g1 + raise haxe_Exception.thrown(((("Unexpected '" + ("null" if s is None else s)) + "' in ") + ("null" if expr is None else expr))) + else: + raise _g + def _hx_local_0(): + try: + return e() + except BaseException as _g: + None + exc = haxe_Exception.caught(_g).unwrap() + raise haxe_Exception.thrown(((("Error : " + Std.string(exc)) + " in ") + ("null" if expr is None else expr))) + return _hx_local_0 + + def makeConst(self,v): + _this = haxe_Template.expr_trim + _this.matchObj = python_lib_Re.search(_this.pattern,v) + v = haxe_Template.expr_trim.matchObj.group(1) + if (HxString.charCodeAt(v,0) == 34): + _hx_str = HxString.substr(v,1,(len(v) - 2)) + def _hx_local_0(): + return _hx_str + return _hx_local_0 + _this = haxe_Template.expr_int + _this.matchObj = python_lib_Re.search(_this.pattern,v) + if (_this.matchObj is not None): + i = Std.parseInt(v) + def _hx_local_1(): + return i + return _hx_local_1 + _this = haxe_Template.expr_float + _this.matchObj = python_lib_Re.search(_this.pattern,v) + if (_this.matchObj is not None): + f = Std.parseFloat(v) + def _hx_local_2(): + return f + return _hx_local_2 + me = self + def _hx_local_3(): + return me.resolve(v) + return _hx_local_3 + + def makePath(self,e,l): + p = l.first() + if ((p is None) or ((p.p != "."))): + return e + l.pop() + field = l.pop() + if ((field is None) or (not field.s)): + raise haxe_Exception.thrown(field.p) + f = field.p + _this = haxe_Template.expr_trim + _this.matchObj = python_lib_Re.search(_this.pattern,f) + f = haxe_Template.expr_trim.matchObj.group(1) + def _hx_local_1(): + def _hx_local_0(): + return Reflect.field(e(),f) + return self.makePath(_hx_local_0,l) + return _hx_local_1() + + def makeExpr(self,l): + return self.makePath(self.makeExpr2(l),l) + + def skipSpaces(self,l): + p = l.first() + while (p is not None): + _g_offset = 0 + _g_s = p.p + while (_g_offset < len(_g_s)): + index = _g_offset + _g_offset = (_g_offset + 1) + c = ord(_g_s[index]) + if (c != 32): + return + l.pop() + p = l.first() + + def makeExpr2(self,l): + self.skipSpaces(l) + p = l.pop() + self.skipSpaces(l) + if (p is None): + raise haxe_Exception.thrown("") + if p.s: + return self.makeConst(p.p) + _g = p.p + if (_g == "!"): + e = self.makeExpr(l) + def _hx_local_0(): + v = e() + if (v is not None): + return (v == False) + else: + return True + return _hx_local_0 + elif (_g == "("): + self.skipSpaces(l) + e1 = self.makeExpr(l) + self.skipSpaces(l) + p1 = l.pop() + if ((p1 is None) or p1.s): + raise haxe_Exception.thrown(p1) + if (p1.p == ")"): + return e1 + self.skipSpaces(l) + e2 = self.makeExpr(l) + self.skipSpaces(l) + p2 = l.pop() + self.skipSpaces(l) + if ((p2 is None) or ((p2.p != ")"))): + raise haxe_Exception.thrown(p2) + _g = p1.p + _hx_local_1 = len(_g) + if (_hx_local_1 == 1): + if (_g == "*"): + def _hx_local_2(): + return (e1() * e2()) + return _hx_local_2 + elif (_g == "+"): + def _hx_local_3(): + return python_Boot._add_dynamic(e1(),e2()) + return _hx_local_3 + elif (_g == "-"): + def _hx_local_4(): + return (e1() - e2()) + return _hx_local_4 + elif (_g == "/"): + def _hx_local_5(): + return (e1() / e2()) + return _hx_local_5 + elif (_g == "<"): + def _hx_local_6(): + return (e1() < e2()) + return _hx_local_6 + elif (_g == ">"): + def _hx_local_7(): + return (e1() > e2()) + return _hx_local_7 + else: + raise haxe_Exception.thrown(("Unknown operation " + HxOverrides.stringOrNull(p1.p))) + elif (_hx_local_1 == 2): + if (_g == "!="): + def _hx_local_8(): + return not HxOverrides.eq(e1(),e2()) + return _hx_local_8 + elif (_g == "&&"): + def _hx_local_9(): + return (e1() and e2()) + return _hx_local_9 + elif (_g == "<="): + def _hx_local_10(): + return (e1() <= e2()) + return _hx_local_10 + elif (_g == "=="): + def _hx_local_11(): + return HxOverrides.eq(e1(),e2()) + return _hx_local_11 + elif (_g == ">="): + def _hx_local_12(): + return (e1() >= e2()) + return _hx_local_12 + elif (_g == "||"): + def _hx_local_13(): + return (e1() or e2()) + return _hx_local_13 + else: + raise haxe_Exception.thrown(("Unknown operation " + HxOverrides.stringOrNull(p1.p))) + else: + raise haxe_Exception.thrown(("Unknown operation " + HxOverrides.stringOrNull(p1.p))) + elif (_g == "-"): + e3 = self.makeExpr(l) + def _hx_local_14(): + return -e3() + return _hx_local_14 + else: + pass + raise haxe_Exception.thrown(p.p) + + def run(self,e): + tmp = e.index + if (tmp == 0): + v = e.params[0] + _this = self.buf + s = Std.string(Std.string(self.resolve(v))) + _this.b.write(s) + elif (tmp == 1): + e1 = e.params[0] + _this = self.buf + s = Std.string(Std.string(e1())) + _this.b.write(s) + elif (tmp == 2): + e1 = e.params[0] + eif = e.params[1] + eelse = e.params[2] + v = e1() + if ((v is None) or ((v == False))): + if (eelse is not None): + self.run(eelse) + else: + self.run(eif) + elif (tmp == 3): + _hx_str = e.params[0] + _this = self.buf + s = Std.string(_hx_str) + _this.b.write(s) + elif (tmp == 4): + l = e.params[0] + _g_head = l.h + while (_g_head is not None): + val = _g_head.item + _g_head = _g_head.next + e1 = val + self.run(e1) + elif (tmp == 5): + e1 = e.params[0] + loop = e.params[1] + v = e1() + try: + x = Reflect.field(v,"iterator")() + if (Reflect.field(x,"hasNext") is None): + raise haxe_Exception.thrown(None) + v = x + except BaseException as _g: + None + try: + if (Reflect.field(v,"hasNext") is None): + raise haxe_Exception.thrown(None) + except BaseException as _g: + raise haxe_Exception.thrown(("Cannot iter on " + Std.string(v))) + self.stack.push(self.context) + v1 = v + ctx = v1 + while ctx.hasNext(): + ctx1 = ctx.next() + self.context = ctx1 + self.run(loop) + self.context = self.stack.pop() + elif (tmp == 6): + m = e.params[0] + params = e.params[1] + v = Reflect.field(self.macros,m) + pl = list() + old = self.buf + pl.append(self.resolve) + _g_head = params.h + while (_g_head is not None): + val = _g_head.item + _g_head = _g_head.next + p = val + if (p.index == 0): + v1 = p.params[0] + x = self.resolve(v1) + pl.append(x) + else: + self.buf = StringBuf() + self.run(p) + x1 = self.buf.b.getvalue() + pl.append(x1) + self.buf = old + try: + _this = self.buf + s = Std.string(Std.string(Reflect.callMethod(self.macros,v,pl))) + _this.b.write(s) + except BaseException as _g: + None + e = haxe_Exception.caught(_g).unwrap() + plstr = None + try: + plstr = ",".join([python_Boot.toString1(x1,'') for x1 in pl]) + except BaseException as _g: + plstr = "???" + msg = (((((("Macro call " + ("null" if m is None else m)) + "(") + ("null" if plstr is None else plstr)) + ") failed (") + Std.string(e)) + ")") + raise haxe_Exception.thrown(msg) + else: + pass + +haxe_Template._hx_class = haxe_Template + + +class haxe_ValueException(haxe_Exception): + _hx_class_name = "haxe.ValueException" + __slots__ = ("value",) + _hx_fields = ["value"] + _hx_methods = ["unwrap"] + _hx_statics = [] + _hx_interfaces = [] + _hx_super = haxe_Exception + + + def __init__(self,value,previous = None,native = None): + self.value = None + super().__init__(Std.string(value),previous,native) + self.value = value + + def unwrap(self): + return self.value + +haxe_ValueException._hx_class = haxe_ValueException + + +class haxe_ds_List: + _hx_class_name = "haxe.ds.List" + __slots__ = ("h", "q", "length") + _hx_fields = ["h", "q", "length"] + _hx_methods = ["add", "push", "first", "pop", "isEmpty", "toString"] + + def __init__(self): + self.q = None + self.h = None + self.length = 0 + + def add(self,item): + x = haxe_ds__List_ListNode(item,None) + if (self.h is None): + self.h = x + else: + self.q.next = x + self.q = x + _hx_local_0 = self + _hx_local_1 = _hx_local_0.length + _hx_local_0.length = (_hx_local_1 + 1) + _hx_local_1 + + def push(self,item): + x = haxe_ds__List_ListNode(item,self.h) + self.h = x + if (self.q is None): + self.q = x + _hx_local_0 = self + _hx_local_1 = _hx_local_0.length + _hx_local_0.length = (_hx_local_1 + 1) + _hx_local_1 + + def first(self): + if (self.h is None): + return None + else: + return self.h.item + + def pop(self): + if (self.h is None): + return None + x = self.h.item + self.h = self.h.next + if (self.h is None): + self.q = None + _hx_local_0 = self + _hx_local_1 = _hx_local_0.length + _hx_local_0.length = (_hx_local_1 - 1) + _hx_local_1 + return x + + def isEmpty(self): + return (self.h is None) + + def toString(self): + s_b = python_lib_io_StringIO() + first = True + l = self.h + s_b.write("{") + while (l is not None): + if first: + first = False + else: + s_b.write(", ") + s_b.write(Std.string(Std.string(l.item))) + l = l.next + s_b.write("}") + return s_b.getvalue() + +haxe_ds_List._hx_class = haxe_ds_List + + +class haxe_ds__List_ListNode: + _hx_class_name = "haxe.ds._List.ListNode" + __slots__ = ("item", "next") + _hx_fields = ["item", "next"] + + def __init__(self,item,next): + self.item = item + self.next = next + +haxe_ds__List_ListNode._hx_class = haxe_ds__List_ListNode + + +class haxe_ds_StringMap: + _hx_class_name = "haxe.ds.StringMap" + __slots__ = ("h",) + _hx_fields = ["h"] + _hx_interfaces = [haxe_IMap] + + def __init__(self): + self.h = dict() + +haxe_ds_StringMap._hx_class = haxe_ds_StringMap class haxe_iterators_ArrayKeyValueIterator: @@ -678,12 +1409,21 @@ class haxe_iterators_ArrayKeyValueIterator: return _hx_AnonObject({'value': python_internal_ArrayImpl._get(self.array, self.current), 'key': _hx_local_2()}) return _hx_local_3() +haxe_iterators_ArrayKeyValueIterator._hx_class = haxe_iterators_ArrayKeyValueIterator class python_Boot: _hx_class_name = "python.Boot" __slots__ = () - _hx_statics = ["keywords", "toString1", "fields", "simpleField", "hasField", "field", "getInstanceFields", "getSuperClass", "getClassFields", "prefixLength", "unhandleKeywords"] + _hx_statics = ["keywords", "_add_dynamic", "toString1", "fields", "simpleField", "hasField", "field", "getInstanceFields", "getSuperClass", "getClassFields", "prefixLength", "unhandleKeywords"] + + @staticmethod + def _add_dynamic(a,b): + if (isinstance(a,str) and isinstance(b,str)): + return (a + b) + if (isinstance(a,str) or isinstance(b,str)): + return (python_Boot.toString1(a,"") + python_Boot.toString1(b,"")) + return (a + b) @staticmethod def toString1(o,s): @@ -1099,6 +1839,7 @@ class python_Boot: if (real in python_Boot.keywords): return real return name +python_Boot._hx_class = python_Boot class python_HaxeIterator: @@ -1134,12 +1875,13 @@ class python_HaxeIterator: self.checked = True return self.has +python_HaxeIterator._hx_class = python_HaxeIterator class python_internal_ArrayImpl: _hx_class_name = "python.internal.ArrayImpl" __slots__ = () - _hx_statics = ["get_length", "concat", "copy", "iterator", "keyValueIterator", "indexOf", "lastIndexOf", "join", "toString", "pop", "push", "unshift", "remove", "contains", "shift", "slice", "sort", "splice", "map", "filter", "insert", "reverse", "_get"] + _hx_statics = ["get_length", "concat", "copy", "iterator", "keyValueIterator", "indexOf", "lastIndexOf", "join", "toString", "pop", "push", "unshift", "remove", "contains", "shift", "slice", "sort", "splice", "map", "filter", "insert", "reverse", "_get", "_set"] @staticmethod def get_length(x): @@ -1275,11 +2017,30 @@ class python_internal_ArrayImpl: else: return None + @staticmethod + def _set(x,idx,v): + l = len(x) + while (l < idx): + x.append(None) + l = (l + 1) + if (l == idx): + x.append(v) + else: + x[idx] = v + return v +python_internal_ArrayImpl._hx_class = python_internal_ArrayImpl + class HxOverrides: _hx_class_name = "HxOverrides" __slots__ = () - _hx_statics = ["eq", "stringOrNull", "filter", "length", "arrayGet"] + _hx_statics = ["iterator", "eq", "stringOrNull", "filter", "length", "arrayGet"] + + @staticmethod + def iterator(x): + if isinstance(x,list): + return haxe_iterators_ArrayIterator(x) + return x.iterator() @staticmethod def eq(a,b): @@ -1318,6 +2079,7 @@ class HxOverrides: return None else: return a[i] +HxOverrides._hx_class = HxOverrides class python_internal_MethodClosure: @@ -1333,6 +2095,7 @@ class python_internal_MethodClosure: def __call__(self,*args): return self.func(self.obj,*args) +python_internal_MethodClosure._hx_class = python_internal_MethodClosure class HxString: @@ -1447,6 +2210,7 @@ class HxString: if (startIndex < 0): startIndex = 0 return s[startIndex:(startIndex + _hx_len)] +HxString._hx_class = HxString class xrfragment_Filter: @@ -1555,8 +2319,8 @@ class xrfragment_Filter: fails = 0 qualify = 0 def _hx_local_2(expr): - nonlocal conds nonlocal fails + nonlocal conds conds = (conds + 1) fails = (fails + (0 if expr else 1)) return expr @@ -1581,6 +2345,7 @@ class xrfragment_Filter: qualify = (qualify + 1) return (qualify > 0) +xrfragment_Filter._hx_class = xrfragment_Filter class xrfragment_Parser: @@ -1591,26 +2356,30 @@ class xrfragment_Parser: @staticmethod def parse(key,value,store,index = None): Frag = haxe_ds_StringMap() - Frag.h["#"] = ((xrfragment_XRF.ASSET | xrfragment_XRF.T_PREDEFINED_VIEW) | xrfragment_XRF.PV_EXECUTE) - Frag.h["src"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_URL) - Frag.h["href"] = ((xrfragment_XRF.ASSET | xrfragment_XRF.T_URL) | xrfragment_XRF.T_PREDEFINED_VIEW) - Frag.h["tag"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING) + Frag.h["#"] = ((xrfragment_XRF.IMMUTABLE | xrfragment_XRF.T_PREDEFINED_VIEW) | xrfragment_XRF.PV_EXECUTE) + Frag.h["src"] = xrfragment_XRF.T_URL + Frag.h["href"] = (xrfragment_XRF.T_URL | xrfragment_XRF.T_PREDEFINED_VIEW) + Frag.h["tag"] = (xrfragment_XRF.IMMUTABLE | xrfragment_XRF.T_STRING) Frag.h["pos"] = ((((xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_VECTOR3) | xrfragment_XRF.T_STRING) | xrfragment_XRF.METADATA) | xrfragment_XRF.NAVIGATOR) Frag.h["rot"] = ((((xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_VECTOR3) | xrfragment_XRF.METADATA) | xrfragment_XRF.NAVIGATOR) - Frag.h["t"] = ((((((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_FLOAT) | xrfragment_XRF.T_VECTOR2) | xrfragment_XRF.T_MEDIAFRAG) | xrfragment_XRF.NAVIGATOR) | xrfragment_XRF.METADATA) - Frag.h["xywh"] = ((((((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_FLOAT) | xrfragment_XRF.T_VECTOR2) | xrfragment_XRF.T_MEDIAFRAG) | xrfragment_XRF.NAVIGATOR) | xrfragment_XRF.METADATA) - Frag.h["namespace"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING) - Frag.h["SPDX"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING) - Frag.h["unit"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING) - Frag.h["description"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING) - Frag.h["session"] = (((((xrfragment_XRF.ASSET | xrfragment_XRF.T_URL) | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.NAVIGATOR) | xrfragment_XRF.METADATA) | xrfragment_XRF.PROMPT) + Frag.h["t"] = ((((xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_FLOAT) | xrfragment_XRF.T_VECTOR2) | xrfragment_XRF.NAVIGATOR) | xrfragment_XRF.METADATA) + Frag.h["s"] = (xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_MEDIAFRAG) + Frag.h["loop"] = xrfragment_XRF.PV_OVERRIDE + Frag.h["uv"] = (xrfragment_XRF.T_VECTOR2 | xrfragment_XRF.T_MEDIAFRAG) + Frag.h["namespace"] = (xrfragment_XRF.IMMUTABLE | xrfragment_XRF.T_STRING) + Frag.h["SPDX"] = (xrfragment_XRF.IMMUTABLE | xrfragment_XRF.T_STRING) + Frag.h["unit"] = (xrfragment_XRF.IMMUTABLE | xrfragment_XRF.T_STRING) + Frag.h["description"] = (xrfragment_XRF.IMMUTABLE | xrfragment_XRF.T_STRING) keyStripped = xrfragment_XRF.operators.replace(key,"") isPVDynamic = ((len(key) > 0) and (not (key in Frag.h))) - isPVDefault = (((len(value) == 0) and ((len(key) > 0))) and ((key == "#"))) if isPVDynamic: v = xrfragment_XRF(key,(xrfragment_XRF.PV_EXECUTE | xrfragment_XRF.NAVIGATOR),index) v.validate(value) - v.flags = xrfragment_XRF.set(xrfragment_XRF.T_DYNAMIC,v.flags) + v.flags = xrfragment_XRF.set(xrfragment_XRF.T_DYNAMICKEY,v.flags) + if (not (key in Frag.h)): + v.flags = xrfragment_XRF.set(xrfragment_XRF.CUSTOMFRAG,v.flags) + if (len(value) == 0): + v.flags = xrfragment_XRF.set(xrfragment_XRF.T_DYNAMICKEYVALUE,v.flags) setattr(store,(("_hx_" + keyStripped) if ((keyStripped in python_Boot.keywords)) else (("_hx_" + keyStripped) if (((((len(keyStripped) > 2) and ((ord(keyStripped[0]) == 95))) and ((ord(keyStripped[1]) == 95))) and ((ord(keyStripped[(len(keyStripped) - 1)]) != 95)))) else keyStripped)),v) return True v = xrfragment_XRF(key,Frag.h.get(key,None),index) @@ -1624,15 +2393,16 @@ class xrfragment_Parser: else: if Std.isOfType(value,str): v.guessType(v,value) - v.noXRF = True + v.flags = xrfragment_XRF.set(xrfragment_XRF.CUSTOMFRAG,v.flags) setattr(store,(("_hx_" + keyStripped) if ((keyStripped in python_Boot.keywords)) else (("_hx_" + keyStripped) if (((((len(keyStripped) > 2) and ((ord(keyStripped[0]) == 95))) and ((ord(keyStripped[1]) == 95))) and ((ord(keyStripped[(len(keyStripped) - 1)]) != 95)))) else keyStripped)),v) return True +xrfragment_Parser._hx_class = xrfragment_Parser class xrfragment_URI: _hx_class_name = "xrfragment.URI" __slots__ = () - _hx_statics = ["parse"] + _hx_statics = ["__meta__", "parse", "template"] @staticmethod def parse(url,_hx_filter): @@ -1659,8 +2429,13 @@ class xrfragment_URI: key = (splitByEqual[0] if 0 < len(splitByEqual) else None) value = "" if (len(splitByEqual) > 1): - _this1 = regexPlus.split((splitByEqual[1] if 1 < len(splitByEqual) else None)) - value = python_lib_urllib_Parse.unquote(" ".join([python_Boot.toString1(x1,'') for x1 in _this1])) + _this1 = xrfragment_XRF.isVector + _this1.matchObj = python_lib_Re.search(_this1.pattern,(splitByEqual[1] if 1 < len(splitByEqual) else None)) + if (_this1.matchObj is not None): + value = (splitByEqual[1] if 1 < len(splitByEqual) else None) + else: + _this2 = regexPlus.split((splitByEqual[1] if 1 < len(splitByEqual) else None)) + value = python_lib_urllib_Parse.unquote(" ".join([python_Boot.toString1(x1,'') for x1 in _this2])) ok = xrfragment_Parser.parse(key,value,store,i) if ((_hx_filter is not None) and ((_hx_filter != 0))): _g = 0 @@ -1673,16 +2448,32 @@ class xrfragment_URI: Reflect.deleteField(store,key) return store + @staticmethod + def template(uri,vars): + parts = uri.split("#") + if (len(parts) == 1): + return uri + frag = (parts[1] if 1 < len(parts) else None) + frag = StringTools.replace(frag,"{","::") + frag = StringTools.replace(frag,"}","::") + frag = haxe_Template(frag).execute(vars) + frag = StringTools.replace(frag,"null","") + python_internal_ArrayImpl._set(parts, 1, frag) + return "#".join([python_Boot.toString1(x1,'') for x1 in parts]) +xrfragment_URI._hx_class = xrfragment_URI + class xrfragment_XRF: _hx_class_name = "xrfragment.XRF" - __slots__ = ("fragment", "flags", "index", "x", "y", "z", "floats", "speed", "color", "string", "int", "float", "filter", "noXRF") - _hx_fields = ["fragment", "flags", "index", "x", "y", "z", "floats", "speed", "color", "string", "int", "float", "filter", "noXRF"] + __slots__ = ("fragment", "flags", "index", "x", "y", "z", "shift", "floats", "color", "string", "int", "float", "filter", "reset", "loop", "xrfScheme") + _hx_fields = ["fragment", "flags", "index", "x", "y", "z", "shift", "floats", "color", "string", "int", "float", "filter", "reset", "loop", "xrfScheme"] _hx_methods = ["is", "validate", "guessType"] - _hx_statics = ["ASSET", "PROP_BIND", "QUERY_OPERATOR", "PROMPT", "ROUNDROBIN", "NAVIGATOR", "METADATA", "PV_OVERRIDE", "PV_EXECUTE", "T_COLOR", "T_INT", "T_FLOAT", "T_VECTOR2", "T_VECTOR3", "T_URL", "T_PREDEFINED_VIEW", "T_STRING", "T_MEDIAFRAG", "T_DYNAMIC", "isColor", "isInt", "isFloat", "isVector", "isUrl", "isUrlOrPretypedView", "isString", "operators", "isProp", "isExclude", "isDeep", "isNumber", "isMediaFrag", "set", "unset"] + _hx_statics = ["IMMUTABLE", "PROP_BIND", "QUERY_OPERATOR", "PROMPT", "CUSTOMFRAG", "NAVIGATOR", "METADATA", "PV_OVERRIDE", "PV_EXECUTE", "T_COLOR", "T_INT", "T_FLOAT", "T_VECTOR2", "T_VECTOR3", "T_URL", "T_PREDEFINED_VIEW", "T_STRING", "T_MEDIAFRAG", "T_DYNAMICKEY", "T_DYNAMICKEYVALUE", "isColor", "isInt", "isFloat", "isVector", "isUrl", "isUrlOrPretypedView", "isString", "operators", "isProp", "isExclude", "isDeep", "isNumber", "isMediaFrag", "isReset", "isShift", "isXRFScheme", "set", "unset"] def __init__(self,_fragment,_flags,_index = None): - self.noXRF = None + self.xrfScheme = None + self.loop = None + self.reset = None self.filter = None self.float = None self.int = None @@ -1691,8 +2482,8 @@ class xrfragment_XRF: self.z = None self.y = None self.x = None - self.speed = list() self.floats = list() + self.shift = list() self.fragment = _fragment self.flags = _flags self.index = _index @@ -1713,9 +2504,21 @@ class xrfragment_XRF: def guessType(self,v,_hx_str): v.string = _hx_str + _this = xrfragment_XRF.isReset + _this.matchObj = python_lib_Re.search(_this.pattern,v.fragment) + if (_this.matchObj is not None): + v.reset = True + if (v.fragment == "loop"): + v.loop = True if (not Std.isOfType(_hx_str,str)): return if (len(_hx_str) > 0): + _this = xrfragment_XRF.isXRFScheme + _this.matchObj = python_lib_Re.search(_this.pattern,_hx_str) + if (_this.matchObj is not None): + v.xrfScheme = True + _hx_str = xrfragment_XRF.isXRFScheme.replace(_hx_str,"") + v.string = _hx_str if (len(_hx_str.split(",")) > 1): xyzn = _hx_str.split(",") if (len(xyzn) > 0): @@ -1729,9 +2532,14 @@ class xrfragment_XRF: while (_g < _g1): i = _g _g = (_g + 1) - _this = v.floats - x = Std.parseFloat((xyzn[i] if i >= 0 and i < len(xyzn) else None)) + _this = v.shift + _this1 = xrfragment_XRF.isShift + _this1.matchObj = python_lib_Re.search(_this1.pattern,(xyzn[i] if i >= 0 and i < len(xyzn) else None)) + x = (_this1.matchObj is not None) _this.append(x) + _this2 = v.floats + x1 = Std.parseFloat(xrfragment_XRF.isShift.replace((xyzn[i] if i >= 0 and i < len(xyzn) else None),"")) + _this2.append(x1) _this = xrfragment_XRF.isColor _this.matchObj = python_lib_Re.search(_this.pattern,_hx_str) if (_this.matchObj is not None): @@ -1746,22 +2554,9 @@ class xrfragment_XRF: if (_this.matchObj is not None): v.int = Std.parseInt(_hx_str) v.x = v.int - _this = xrfragment_XRF.isMediaFrag - _this.matchObj = python_lib_Re.search(_this.pattern,_hx_str) - if (_this.matchObj is not None): - speed = _hx_str.split("*") - v.speed = list() - if (len(speed) > 1): - _this = (speed[1] if 1 < len(speed) else None) - values = _this.split(",") - _g = 0 - _g1 = len(values) - while (_g < _g1): - i = _g - _g = (_g + 1) - _this = v.speed - x = Std.parseFloat((values[i] if i >= 0 and i < len(values) else None)) - _this.append(x) + _this = v.floats + x = v.x + _this.append(x) v.filter = xrfragment_Filter(((HxOverrides.stringOrNull(v.fragment) + "=") + HxOverrides.stringOrNull(v.string))) else: v.filter = xrfragment_Filter(v.fragment) @@ -1774,6 +2569,7 @@ class xrfragment_XRF: def unset(flag,flags): return (flags & ~flag) +xrfragment_XRF._hx_class = xrfragment_XRF Math.NEGATIVE_INFINITY = float("-inf") Math.POSITIVE_INFINITY = float("inf") @@ -1781,15 +2577,23 @@ Math.NaN = float("nan") Math.PI = python_lib_Math.pi Test.errors = 0 +haxe_Template.splitter = EReg("(::[A-Za-z0-9_ ()&|!+=/><*.\"-]+::|\\$\\$([A-Za-z0-9_-]+)\\()","") +haxe_Template.expr_splitter = EReg("(\\(|\\)|[ \r\n\t]*\"[^\"]*\"[ \r\n\t]*|[!+=/><*.&|-]+)","") +haxe_Template.expr_trim = EReg("^[ ]*([^ ]+)[ ]*$","") +haxe_Template.expr_int = EReg("^[0-9]+$","") +haxe_Template.expr_float = EReg("^([+-]?)(?=\\d|,\\d)\\d*(,\\d*)?([Ee]([+-]?\\d+))?$","") +haxe_Template.globals = _hx_AnonObject({}) +haxe_Template.hxKeepArrayIterator = haxe_iterators_ArrayIterator([]) python_Boot.keywords = set(["and", "del", "from", "not", "with", "as", "elif", "global", "or", "yield", "assert", "else", "if", "pass", "None", "break", "except", "import", "raise", "True", "class", "exec", "in", "return", "False", "continue", "finally", "is", "try", "def", "for", "lambda", "while"]) python_Boot.prefixLength = len("_hx_") xrfragment_Parser.error = "" xrfragment_Parser.debug = False -xrfragment_XRF.ASSET = 1 +xrfragment_URI.__meta__ = _hx_AnonObject({'statics': _hx_AnonObject({'template': _hx_AnonObject({'keep': None})})}) +xrfragment_XRF.IMMUTABLE = 1 xrfragment_XRF.PROP_BIND = 2 xrfragment_XRF.QUERY_OPERATOR = 4 xrfragment_XRF.PROMPT = 8 -xrfragment_XRF.ROUNDROBIN = 16 +xrfragment_XRF.CUSTOMFRAG = 16 xrfragment_XRF.NAVIGATOR = 32 xrfragment_XRF.METADATA = 64 xrfragment_XRF.PV_OVERRIDE = 128 @@ -1803,7 +2607,8 @@ xrfragment_XRF.T_URL = 262144 xrfragment_XRF.T_PREDEFINED_VIEW = 524288 xrfragment_XRF.T_STRING = 1048576 xrfragment_XRF.T_MEDIAFRAG = 2097152 -xrfragment_XRF.T_DYNAMIC = 4194304 +xrfragment_XRF.T_DYNAMICKEY = 4194304 +xrfragment_XRF.T_DYNAMICKEYVALUE = 8388608 xrfragment_XRF.isColor = EReg("^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$","") xrfragment_XRF.isInt = EReg("^[-0-9]+$","") xrfragment_XRF.isFloat = EReg("^[-0-9]+\\.[0-9]+$","") @@ -1811,11 +2616,14 @@ xrfragment_XRF.isVector = EReg("([,]+|\\w)","") xrfragment_XRF.isUrl = EReg("(://)?\\..*","") xrfragment_XRF.isUrlOrPretypedView = EReg("(^#|://)?\\..*","") xrfragment_XRF.isString = EReg(".*","") -xrfragment_XRF.operators = EReg("(^-|[\\*]+)","") +xrfragment_XRF.operators = EReg("(^[-]|^[!]|[\\*]$)","g") xrfragment_XRF.isProp = EReg("^.*=[><=]?","") xrfragment_XRF.isExclude = EReg("^-","") xrfragment_XRF.isDeep = EReg("\\*","") xrfragment_XRF.isNumber = EReg("^[0-9\\.]+$","") -xrfragment_XRF.isMediaFrag = EReg("^[0-9\\.,\\*]+$","") +xrfragment_XRF.isMediaFrag = EReg("^([0-9\\.,\\*+-]+)$","") +xrfragment_XRF.isReset = EReg("^!","") +xrfragment_XRF.isShift = EReg("^(\\+|--)","") +xrfragment_XRF.isXRFScheme = EReg("^xrf://","") Test.main()