mirror of
https://github.com/Orange-OpenSource/hurl.git
synced 2024-11-23 00:44:55 +03:00
Add lang identifier to multiline.
This commit is contained in:
parent
f3bf0b7618
commit
3b3483a997
7
integration/tests_error_parser/multiline.err
Normal file
7
integration/tests_error_parser/multiline.err
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
error: Parsing multine
|
||||||
|
--> tests_error_parser/multiline.hurl:2:4
|
||||||
|
|
|
||||||
|
2 | ```foo
|
||||||
|
| ^ the multiline is not valid
|
||||||
|
|
|
||||||
|
|
2
integration/tests_error_parser/multiline.exit
Normal file
2
integration/tests_error_parser/multiline.exit
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
2
|
||||||
|
|
6
integration/tests_error_parser/multiline.hurl
Normal file
6
integration/tests_error_parser/multiline.hurl
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
GET http://localhost:8000/invalid-multiline
|
||||||
|
```foo
|
||||||
|
bar
|
||||||
|
baz
|
||||||
|
```
|
||||||
|
HTTP 200
|
@ -1,8 +1,8 @@
|
|||||||
error: Assert body value
|
error: Assert body value
|
||||||
--> tests_failed/assert_newline.hurl:9:4
|
--> tests_failed/assert_newline.hurl:10:1
|
||||||
|
|
|
|
||||||
9 | ```<p>Hello</p>
|
10 | <p>Hello</p>
|
||||||
| ^ actual value is <<p>Hello</p>
|
| ^ actual value is <<p>Hello</p>
|
||||||
|
|
||||||
>
|
>
|
||||||
|
|
|
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
<span class="line"></span><span class="comment"># It should produce an assert error</span>
|
<span class="line"></span><span class="comment"># It should produce an assert error</span>
|
||||||
<span class="line"><span class="method">GET</span> <span class="url">http://localhost:8000/error-assert-newline</span></span>
|
<span class="line"><span class="method">GET</span> <span class="url">http://localhost:8000/error-assert-newline</span></span>
|
||||||
</span><span class="response"><span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
|
</span><span class="response"><span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
|
||||||
<span class="raw"><span class="line">```<p>Hello</p></span>
|
<span class="raw"><span class="line">```</span>
|
||||||
|
<span class="line"><p>Hello</p></span>
|
||||||
<span class="line">```</span></span>
|
<span class="line">```</span></span>
|
||||||
</span></span><span class="line"></span>
|
</span></span><span class="line"></span>
|
||||||
<span class="line"></span><span class="comment"># TODO</span>
|
<span class="line"></span><span class="comment"># TODO</span>
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
# It should produce an assert error
|
# It should produce an assert error
|
||||||
GET http://localhost:8000/error-assert-newline
|
GET http://localhost:8000/error-assert-newline
|
||||||
HTTP 200
|
HTTP 200
|
||||||
```<p>Hello</p>
|
```
|
||||||
|
<p>Hello</p>
|
||||||
```
|
```
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
|
@ -1,15 +1,80 @@
|
|||||||
<pre><code class="language-hurl"><span class="hurl-entry"><span class="request"><span class="line"><span class="method">GET</span> <span class="url">http://localhost:8000/multilines</span></span>
|
<pre><code class="language-hurl"><span class="hurl-entry"><span class="request"><span class="line"><span class="method">GET</span> <span class="url">http://localhost:8000/multilines/plain-text</span></span>
|
||||||
</span><span class="response"><span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
|
</span><span class="response"><span class="line"></span>
|
||||||
|
<span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
|
||||||
<span class="line section-header">[Asserts]</span>
|
<span class="line section-header">[Asserts]</span>
|
||||||
<span class="line"><span class="query-type">body</span> <span class="predicate-type">==</span> <span class="string">"line1\nline2\nline3\n"</span></span>
|
<span class="line"><span class="query-type">body</span> <span class="predicate-type">==</span> <span class="string">"line1\nline2\nline3\n"</span></span>
|
||||||
<span class="line"><span class="query-type">body</span> <span class="predicate-type">==</span> <span class="raw"><span class="line">```line1</span>
|
|
||||||
<span class="line">line2</span>
|
|
||||||
<span class="line">line3</span>
|
|
||||||
<span class="line">```</span></span></span>
|
|
||||||
<span class="line"><span class="query-type">body</span> <span class="predicate-type">==</span> <span class="raw"><span class="line">```</span>
|
<span class="line"><span class="query-type">body</span> <span class="predicate-type">==</span> <span class="raw"><span class="line">```</span>
|
||||||
<span class="line">line1</span>
|
<span class="line">line1</span>
|
||||||
<span class="line">line2</span>
|
<span class="line">line2</span>
|
||||||
<span class="line">line3</span>
|
<span class="line">line3</span>
|
||||||
<span class="line">```</span></span></span>
|
<span class="line">```</span></span></span>
|
||||||
</span></span><span class="line"></span>
|
</span></span><span class="hurl-entry"><span class="request"><span class="line"></span>
|
||||||
</code></pre>
|
<span class="line"></span>
|
||||||
|
<span class="line"><span class="method">GET</span> <span class="url">http://localhost:8000/multilines/base64</span></span>
|
||||||
|
</span><span class="response"><span class="line"></span>
|
||||||
|
<span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
|
||||||
|
<span class="raw"><span class="line">```base64</span>
|
||||||
|
<span class="line">TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdCwg</span>
|
||||||
|
<span class="line">c2VkIGRvIGVpdXNtb2QgdGVtcG9yIGluY2lkaWR1bnQgdXQgbGFib3JlIGV0IGRvbG9yZSBtYWdu</span>
|
||||||
|
<span class="line">YSBhbGlxdWEuIFV0IGVuaW0gYWQgbWluaW0gdmVuaWFtLCBxdWlzIG5vc3RydWQgZXhlcmNpdGF0</span>
|
||||||
|
<span class="line">aW9uIHVsbGFtY28gbGFib3JpcyBuaXNpIHV0IGFsaXF1aXAgZXggZWEgY29tbW9kbyBjb25zZXF1</span>
|
||||||
|
<span class="line">YXQuIER1aXMgYXV0ZSBpcnVyZSBkb2xvciBpbiByZXByZWhlbmRlcml0IGluIHZvbHVwdGF0ZSB2</span>
|
||||||
|
<span class="line">ZWxpdCBlc3NlIGNpbGx1bSBkb2xvcmUgZXUgZnVnaWF0IG51bGxhIHBhcmlhdHVyLiBFeGNlcHRl</span>
|
||||||
|
<span class="line">dXIgc2ludCBvY2NhZWNhdCBjdXBpZGF0YXQgbm9uIHByb2lkZW50LCBzdW50IGluIGN1bHBhIHF1</span>
|
||||||
|
<span class="line">aSBvZmZpY2lhIGRlc2VydW50IG1vbGxpdCBhbmltIGlkIGVzdCBsYWJvcnVtLg==</span>
|
||||||
|
<span class="line">```</span></span>
|
||||||
|
</span></span><span class="hurl-entry"><span class="request"><span class="line"></span>
|
||||||
|
<span class="line"></span>
|
||||||
|
<span class="line"><span class="method">GET</span> <span class="url">http://localhost:8000/multilines/hex</span></span>
|
||||||
|
</span><span class="response"><span class="line"></span>
|
||||||
|
<span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
|
||||||
|
<span class="raw"><span class="line">```hex</span>
|
||||||
|
<span class="line">039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81</span>
|
||||||
|
<span class="line">```</span></span>
|
||||||
|
</span></span><span class="hurl-entry"><span class="request"><span class="line"></span>
|
||||||
|
<span class="line"></span>
|
||||||
|
<span class="line"><span class="method">GET</span> <span class="url">http://localhost:8000/multilines/json</span></span>
|
||||||
|
</span><span class="response"><span class="line"></span>
|
||||||
|
<span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
|
||||||
|
<span class="raw"><span class="line">```json</span>
|
||||||
|
<span class="line">{</span>
|
||||||
|
<span class="line"> "foo": "bar"</span>
|
||||||
|
<span class="line"> "baz": 123456</span>
|
||||||
|
<span class="line">}</span>
|
||||||
|
<span class="line">```</span></span>
|
||||||
|
</span></span><span class="hurl-entry"><span class="request"><span class="line"></span>
|
||||||
|
<span class="line"></span>
|
||||||
|
<span class="line"><span class="method">GET</span> <span class="url">http://localhost:8000/multilines/xml</span></span>
|
||||||
|
</span><span class="response"><span class="line"></span>
|
||||||
|
<span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
|
||||||
|
<span class="raw"><span class="line">```xml</span>
|
||||||
|
<span class="line"><?xml version="1.0"?></span>
|
||||||
|
<span class="line"><catalog></span>
|
||||||
|
<span class="line"> <book id="bk101"></span>
|
||||||
|
<span class="line"> <author>Gambardella, Matthew</author></span>
|
||||||
|
<span class="line"> <title>XML Developer's Guide</title></span>
|
||||||
|
<span class="line"> <genre>Computer</genre></span>
|
||||||
|
<span class="line"> <price>44.95</price></span>
|
||||||
|
<span class="line"> <publish_date>2000-10-01</publish_date></span>
|
||||||
|
<span class="line"> <description>An in-depth look at creating applications</span>
|
||||||
|
<span class="line"> with XML.</description></span>
|
||||||
|
<span class="line"> </book></span>
|
||||||
|
<span class="line"></catalog></span>
|
||||||
|
<span class="line">```</span></span>
|
||||||
|
</span></span><span class="hurl-entry"><span class="request"><span class="line"></span>
|
||||||
|
<span class="line"></span>
|
||||||
|
<span class="line"><span class="method">GET</span> <span class="url">http://localhost:8000/multilines/graphql</span></span>
|
||||||
|
</span><span class="response"><span class="line"></span>
|
||||||
|
<span class="line"><span class="version">HTTP</span> <span class="number">200</span></span>
|
||||||
|
<span class="raw"><span class="line">```graphql</span>
|
||||||
|
<span class="line">{</span>
|
||||||
|
<span class="line"> hero {</span>
|
||||||
|
<span class="line"> name</span>
|
||||||
|
<span class="line"> # Queries can have comments!</span>
|
||||||
|
<span class="line"> friends {</span>
|
||||||
|
<span class="line"> name</span>
|
||||||
|
<span class="line"> }</span>
|
||||||
|
<span class="line"> }</span>
|
||||||
|
<span class="line">}</span>
|
||||||
|
<span class="line">```</span></span>
|
||||||
|
</span></span></code></pre>
|
||||||
|
@ -1,14 +1,79 @@
|
|||||||
GET http://localhost:8000/multilines
|
GET http://localhost:8000/multilines/plain-text
|
||||||
|
|
||||||
HTTP 200
|
HTTP 200
|
||||||
[Asserts]
|
[Asserts]
|
||||||
body == "line1\nline2\nline3\n"
|
body == "line1\nline2\nline3\n"
|
||||||
body == ```line1
|
|
||||||
line2
|
|
||||||
line3
|
|
||||||
```
|
|
||||||
body == ```
|
body == ```
|
||||||
line1
|
line1
|
||||||
line2
|
line2
|
||||||
line3
|
line3
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
GET http://localhost:8000/multilines/base64
|
||||||
|
|
||||||
|
HTTP 200
|
||||||
|
```base64
|
||||||
|
TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdCwg
|
||||||
|
c2VkIGRvIGVpdXNtb2QgdGVtcG9yIGluY2lkaWR1bnQgdXQgbGFib3JlIGV0IGRvbG9yZSBtYWdu
|
||||||
|
YSBhbGlxdWEuIFV0IGVuaW0gYWQgbWluaW0gdmVuaWFtLCBxdWlzIG5vc3RydWQgZXhlcmNpdGF0
|
||||||
|
aW9uIHVsbGFtY28gbGFib3JpcyBuaXNpIHV0IGFsaXF1aXAgZXggZWEgY29tbW9kbyBjb25zZXF1
|
||||||
|
YXQuIER1aXMgYXV0ZSBpcnVyZSBkb2xvciBpbiByZXByZWhlbmRlcml0IGluIHZvbHVwdGF0ZSB2
|
||||||
|
ZWxpdCBlc3NlIGNpbGx1bSBkb2xvcmUgZXUgZnVnaWF0IG51bGxhIHBhcmlhdHVyLiBFeGNlcHRl
|
||||||
|
dXIgc2ludCBvY2NhZWNhdCBjdXBpZGF0YXQgbm9uIHByb2lkZW50LCBzdW50IGluIGN1bHBhIHF1
|
||||||
|
aSBvZmZpY2lhIGRlc2VydW50IG1vbGxpdCBhbmltIGlkIGVzdCBsYWJvcnVtLg==
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
GET http://localhost:8000/multilines/hex
|
||||||
|
|
||||||
|
HTTP 200
|
||||||
|
```hex
|
||||||
|
039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
GET http://localhost:8000/multilines/json
|
||||||
|
|
||||||
|
HTTP 200
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"foo": "bar"
|
||||||
|
"baz": 123456
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
GET http://localhost:8000/multilines/xml
|
||||||
|
|
||||||
|
HTTP 200
|
||||||
|
```xml
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<catalog>
|
||||||
|
<book id="bk101">
|
||||||
|
<author>Gambardella, Matthew</author>
|
||||||
|
<title>XML Developer's Guide</title>
|
||||||
|
<genre>Computer</genre>
|
||||||
|
<price>44.95</price>
|
||||||
|
<publish_date>2000-10-01</publish_date>
|
||||||
|
<description>An in-depth look at creating applications
|
||||||
|
with XML.</description>
|
||||||
|
</book>
|
||||||
|
</catalog>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
GET http://localhost:8000/multilines/graphql
|
||||||
|
|
||||||
|
HTTP 200
|
||||||
|
```graphql
|
||||||
|
{
|
||||||
|
hero {
|
||||||
|
name
|
||||||
|
# Queries can have comments!
|
||||||
|
friends {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
@ -1 +1 @@
|
|||||||
{"entries":[{"request":{"method":"GET","url":"http://localhost:8000/multilines"},"response":{"status":200,"asserts":[{"query":{"type":"body"},"predicate":{"type":"equal","value":"line1\nline2\nline3\n"}},{"query":{"type":"body"},"predicate":{"type":"equal","value":"line1\nline2\nline3\n"}},{"query":{"type":"body"},"predicate":{"type":"equal","value":"line1\nline2\nline3\n"}}]}}]}
|
{"entries":[{"request":{"method":"GET","url":"http://localhost:8000/multilines/plain-text"},"response":{"status":200,"asserts":[{"query":{"type":"body"},"predicate":{"type":"equal","value":"line1\nline2\nline3\n"}},{"query":{"type":"body"},"predicate":{"type":"equal","value":"line1\nline2\nline3\n"}}]}},{"request":{"method":"GET","url":"http://localhost:8000/multilines/base64"},"response":{"status":200,"body":{"type":"base64","value":"TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdCwg\nc2VkIGRvIGVpdXNtb2QgdGVtcG9yIGluY2lkaWR1bnQgdXQgbGFib3JlIGV0IGRvbG9yZSBtYWdu\nYSBhbGlxdWEuIFV0IGVuaW0gYWQgbWluaW0gdmVuaWFtLCBxdWlzIG5vc3RydWQgZXhlcmNpdGF0\naW9uIHVsbGFtY28gbGFib3JpcyBuaXNpIHV0IGFsaXF1aXAgZXggZWEgY29tbW9kbyBjb25zZXF1\nYXQuIER1aXMgYXV0ZSBpcnVyZSBkb2xvciBpbiByZXByZWhlbmRlcml0IGluIHZvbHVwdGF0ZSB2\nZWxpdCBlc3NlIGNpbGx1bSBkb2xvcmUgZXUgZnVnaWF0IG51bGxhIHBhcmlhdHVyLiBFeGNlcHRl\ndXIgc2ludCBvY2NhZWNhdCBjdXBpZGF0YXQgbm9uIHByb2lkZW50LCBzdW50IGluIGN1bHBhIHF1\naSBvZmZpY2lhIGRlc2VydW50IG1vbGxpdCBhbmltIGlkIGVzdCBsYWJvcnVtLg==\n"}}},{"request":{"method":"GET","url":"http://localhost:8000/multilines/hex"},"response":{"status":200,"body":{"type":"hex","value":"039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81\n"}}},{"request":{"method":"GET","url":"http://localhost:8000/multilines/json"},"response":{"status":200,"body":{"type":"json","value":"{\n \"foo\": \"bar\"\n \"baz\": 123456\n}\n"}}},{"request":{"method":"GET","url":"http://localhost:8000/multilines/xml"},"response":{"status":200,"body":{"type":"xml","value":"<?xml version=\"1.0\"?>\n<catalog>\n <book id=\"bk101\">\n <author>Gambardella, Matthew</author>\n <title>XML Developer's Guide</title>\n <genre>Computer</genre>\n <price>44.95</price>\n <publish_date>2000-10-01</publish_date>\n <description>An in-depth look at creating applications\n with XML.</description>\n </book>\n</catalog>\n"}}},{"request":{"method":"GET","url":"http://localhost:8000/multilines/graphql"},"response":{"status":200,"body":{"type":"graphql","value":"{\n hero {\n name\n # Queries can have comments!\n friends {\n name\n }\n }\n}\n"}}}]}
|
||||||
|
@ -1,6 +1,68 @@
|
|||||||
from app import app
|
from app import app
|
||||||
|
|
||||||
|
|
||||||
@app.route("/multilines")
|
@app.route("/multilines/plain-text")
|
||||||
def multilines():
|
def multilines_plain_text():
|
||||||
return "line1\nline2\nline3\n"
|
return "line1\nline2\nline3\n"
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/multilines/base64")
|
||||||
|
def multilines_base64():
|
||||||
|
return """\
|
||||||
|
TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdCwg
|
||||||
|
c2VkIGRvIGVpdXNtb2QgdGVtcG9yIGluY2lkaWR1bnQgdXQgbGFib3JlIGV0IGRvbG9yZSBtYWdu
|
||||||
|
YSBhbGlxdWEuIFV0IGVuaW0gYWQgbWluaW0gdmVuaWFtLCBxdWlzIG5vc3RydWQgZXhlcmNpdGF0
|
||||||
|
aW9uIHVsbGFtY28gbGFib3JpcyBuaXNpIHV0IGFsaXF1aXAgZXggZWEgY29tbW9kbyBjb25zZXF1
|
||||||
|
YXQuIER1aXMgYXV0ZSBpcnVyZSBkb2xvciBpbiByZXByZWhlbmRlcml0IGluIHZvbHVwdGF0ZSB2
|
||||||
|
ZWxpdCBlc3NlIGNpbGx1bSBkb2xvcmUgZXUgZnVnaWF0IG51bGxhIHBhcmlhdHVyLiBFeGNlcHRl
|
||||||
|
dXIgc2ludCBvY2NhZWNhdCBjdXBpZGF0YXQgbm9uIHByb2lkZW50LCBzdW50IGluIGN1bHBhIHF1
|
||||||
|
aSBvZmZpY2lhIGRlc2VydW50IG1vbGxpdCBhbmltIGlkIGVzdCBsYWJvcnVtLg==
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/multilines/json")
|
||||||
|
def multilines_json():
|
||||||
|
return """\
|
||||||
|
{
|
||||||
|
"foo": "bar"
|
||||||
|
"baz": 123456
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/multilines/hex")
|
||||||
|
def multilines_hex():
|
||||||
|
return "039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81\n"
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/multilines/xml")
|
||||||
|
def multilines_xml():
|
||||||
|
return """\
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<catalog>
|
||||||
|
<book id="bk101">
|
||||||
|
<author>Gambardella, Matthew</author>
|
||||||
|
<title>XML Developer's Guide</title>
|
||||||
|
<genre>Computer</genre>
|
||||||
|
<price>44.95</price>
|
||||||
|
<publish_date>2000-10-01</publish_date>
|
||||||
|
<description>An in-depth look at creating applications
|
||||||
|
with XML.</description>
|
||||||
|
</book>
|
||||||
|
</catalog>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/multilines/graphql")
|
||||||
|
def multilines_graphql():
|
||||||
|
return """\
|
||||||
|
{
|
||||||
|
hero {
|
||||||
|
name
|
||||||
|
# Queries can have comments!
|
||||||
|
friends {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
@ -482,10 +482,26 @@ pub enum PredicateFuncValue {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct RawString {
|
pub struct RawString {
|
||||||
pub newline: Whitespace,
|
pub lang: Option<Lang>,
|
||||||
pub value: Template,
|
pub value: Template,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct Lang {
|
||||||
|
pub value: Option<LangValue>,
|
||||||
|
pub space: Whitespace,
|
||||||
|
pub newline: Whitespace,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub enum LangValue {
|
||||||
|
Base64,
|
||||||
|
Hex,
|
||||||
|
Json,
|
||||||
|
Xml,
|
||||||
|
GraphQl,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct Base64 {
|
pub struct Base64 {
|
||||||
pub space0: Whitespace,
|
pub space0: Whitespace,
|
||||||
|
@ -128,6 +128,19 @@ impl fmt::Display for CookieAttribute {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for LangValue {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
let s = match self {
|
||||||
|
LangValue::Base64 => "base64",
|
||||||
|
LangValue::Hex => "hex",
|
||||||
|
LangValue::Json => "json",
|
||||||
|
LangValue::Xml => "xml",
|
||||||
|
LangValue::GraphQl => "graphql",
|
||||||
|
};
|
||||||
|
write!(f, "{}", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for Hex {
|
impl fmt::Display for Hex {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
|
@ -58,6 +58,7 @@ impl Error for parser::Error {
|
|||||||
ParseError::InvalidCookieAttribute { .. } => "Parsing cookie attribute".to_string(),
|
ParseError::InvalidCookieAttribute { .. } => "Parsing cookie attribute".to_string(),
|
||||||
ParseError::OddNumberOfHexDigits { .. } => "Parsing hex bytearray".to_string(),
|
ParseError::OddNumberOfHexDigits { .. } => "Parsing hex bytearray".to_string(),
|
||||||
ParseError::UrlIllegalCharacter(_) => "Parsing URL".to_string(),
|
ParseError::UrlIllegalCharacter(_) => "Parsing URL".to_string(),
|
||||||
|
ParseError::Multiline => "Parsing multine".to_string(),
|
||||||
_ => format!("{:?}", self),
|
_ => format!("{:?}", self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -109,7 +110,9 @@ impl Error for parser::Error {
|
|||||||
"expecting an even number of hex digits".to_string()
|
"expecting an even number of hex digits".to_string()
|
||||||
}
|
}
|
||||||
ParseError::UrlIllegalCharacter(c) => format!("illegal character <{}>", c),
|
ParseError::UrlIllegalCharacter(c) => format!("illegal character <{}>", c),
|
||||||
|
ParseError::Multiline => "the multiline is not valid".to_string(),
|
||||||
_ => format!("{:?}", self),
|
_ => format!("{:?}", self),
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -859,7 +859,12 @@ impl Htmlable for RawString {
|
|||||||
let mut buffer = "".to_string();
|
let mut buffer = "".to_string();
|
||||||
buffer.push_str("<span class=\"raw\">");
|
buffer.push_str("<span class=\"raw\">");
|
||||||
let mut s = "```".to_string();
|
let mut s = "```".to_string();
|
||||||
s.push_str(self.newline.value.as_str());
|
if let Some(lang) = &self.lang {
|
||||||
|
if let Some(lang_value) = &lang.value {
|
||||||
|
s.push_str(format!("{}", lang_value).as_str());
|
||||||
|
}
|
||||||
|
s.push('\n');
|
||||||
|
}
|
||||||
s.push_str(self.value.to_string().as_str());
|
s.push_str(self.value.to_string().as_str());
|
||||||
s.push_str("```");
|
s.push_str("```");
|
||||||
buffer.push_str(multilines(s).as_str());
|
buffer.push_str(multilines(s).as_str());
|
||||||
@ -1073,10 +1078,7 @@ mod tests {
|
|||||||
fn test_raw_string() {
|
fn test_raw_string() {
|
||||||
// ``````
|
// ``````
|
||||||
let raw_string = RawString {
|
let raw_string = RawString {
|
||||||
newline: Whitespace {
|
lang: None,
|
||||||
value: "".to_string(),
|
|
||||||
source_info: SourceInfo::new(0, 0, 0, 0),
|
|
||||||
},
|
|
||||||
value: Template {
|
value: Template {
|
||||||
quotes: false,
|
quotes: false,
|
||||||
elements: vec![TemplateElement::String {
|
elements: vec![TemplateElement::String {
|
||||||
@ -1093,10 +1095,7 @@ mod tests {
|
|||||||
|
|
||||||
// ```hello```
|
// ```hello```
|
||||||
let raw_string = RawString {
|
let raw_string = RawString {
|
||||||
newline: Whitespace {
|
lang: None,
|
||||||
value: "".to_string(),
|
|
||||||
source_info: SourceInfo::new(0, 0, 0, 0),
|
|
||||||
},
|
|
||||||
value: Template {
|
value: Template {
|
||||||
quotes: false,
|
quotes: false,
|
||||||
elements: vec![TemplateElement::String {
|
elements: vec![TemplateElement::String {
|
||||||
@ -1116,10 +1115,23 @@ mod tests {
|
|||||||
// line2
|
// line2
|
||||||
// ```
|
// ```
|
||||||
let raw_string = RawString {
|
let raw_string = RawString {
|
||||||
newline: Whitespace {
|
lang: Some(Lang {
|
||||||
value: "\n".to_string(),
|
value: None,
|
||||||
source_info: SourceInfo::new(0, 0, 0, 0),
|
space: Whitespace {
|
||||||
},
|
value: "".to_string(),
|
||||||
|
source_info: SourceInfo {
|
||||||
|
start: Pos { line: 1, column: 4 },
|
||||||
|
end: Pos { line: 1, column: 4 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
newline: Whitespace {
|
||||||
|
value: "\n".to_string(),
|
||||||
|
source_info: SourceInfo {
|
||||||
|
start: Pos { line: 1, column: 4 },
|
||||||
|
end: Pos { line: 2, column: 1 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
value: Template {
|
value: Template {
|
||||||
quotes: false,
|
quotes: false,
|
||||||
elements: vec![TemplateElement::String {
|
elements: vec![TemplateElement::String {
|
||||||
@ -1133,27 +1145,6 @@ mod tests {
|
|||||||
raw_string.to_html(),
|
raw_string.to_html(),
|
||||||
"<span class=\"raw\"><span class=\"line\">```</span>\n<span class=\"line\">line1</span>\n<span class=\"line\">line2</span>\n<span class=\"line\">```</span></span>".to_string()
|
"<span class=\"raw\"><span class=\"line\">```</span>\n<span class=\"line\">line1</span>\n<span class=\"line\">line2</span>\n<span class=\"line\">```</span></span>".to_string()
|
||||||
);
|
);
|
||||||
|
|
||||||
// ```Hello
|
|
||||||
// ```
|
|
||||||
let raw_string = RawString {
|
|
||||||
newline: Whitespace {
|
|
||||||
value: "".to_string(),
|
|
||||||
source_info: SourceInfo::new(0, 0, 0, 0),
|
|
||||||
},
|
|
||||||
value: Template {
|
|
||||||
quotes: false,
|
|
||||||
elements: vec![TemplateElement::String {
|
|
||||||
value: "Hello\n".to_string(),
|
|
||||||
encoded: "unused".to_string(),
|
|
||||||
}],
|
|
||||||
source_info: SourceInfo::new(0, 0, 0, 0),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
assert_eq!(
|
|
||||||
raw_string.to_html(),
|
|
||||||
"<span class=\"raw\"><span class=\"line\">```Hello</span>\n<span class=\"line\">```</span></span>".to_string()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
|
use crate::parser::multiline::multiline_string;
|
||||||
|
|
||||||
use super::combinators::*;
|
use super::combinators::*;
|
||||||
use super::json::parse as parse_json;
|
use super::json::parse as parse_json;
|
||||||
@ -25,10 +26,9 @@ use super::xml;
|
|||||||
use super::ParseResult;
|
use super::ParseResult;
|
||||||
|
|
||||||
pub fn bytes(reader: &mut Reader) -> ParseResult<'static, Bytes> {
|
pub fn bytes(reader: &mut Reader) -> ParseResult<'static, Bytes> {
|
||||||
//let start = p.state.clone();
|
|
||||||
choice(
|
choice(
|
||||||
&[
|
&[
|
||||||
raw_string_bytes,
|
multiline_string_bytes,
|
||||||
json_bytes,
|
json_bytes,
|
||||||
xml_bytes,
|
xml_bytes,
|
||||||
base64_bytes,
|
base64_bytes,
|
||||||
@ -38,9 +38,6 @@ pub fn bytes(reader: &mut Reader) -> ParseResult<'static, Bytes> {
|
|||||||
reader,
|
reader,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
fn raw_string_bytes(reader: &mut Reader) -> ParseResult<'static, Bytes> {
|
|
||||||
raw_string(reader).map(Bytes::RawString)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn xml_bytes(reader: &mut Reader) -> ParseResult<'static, Bytes> {
|
fn xml_bytes(reader: &mut Reader) -> ParseResult<'static, Bytes> {
|
||||||
match xml::parse(reader) {
|
match xml::parse(reader) {
|
||||||
@ -68,9 +65,12 @@ fn hex_bytes(reader: &mut Reader) -> ParseResult<'static, Bytes> {
|
|||||||
hex(reader).map(Bytes::Hex)
|
hex(reader).map(Bytes::Hex)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn multiline_string_bytes(reader: &mut Reader) -> ParseResult<'static, Bytes> {
|
||||||
|
multiline_string(reader).map(Bytes::RawString)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use super::super::error::*;
|
use super::super::error::*;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ pub enum ParseError {
|
|||||||
OddNumberOfHexDigits,
|
OddNumberOfHexDigits,
|
||||||
UrlIllegalCharacter(char),
|
UrlIllegalCharacter(char),
|
||||||
InvalidOption,
|
InvalidOption,
|
||||||
|
Multiline,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
|
@ -42,6 +42,7 @@ mod expr;
|
|||||||
mod filename;
|
mod filename;
|
||||||
mod filter;
|
mod filter;
|
||||||
mod json;
|
mod json;
|
||||||
|
mod multiline;
|
||||||
mod parsers;
|
mod parsers;
|
||||||
mod predicate;
|
mod predicate;
|
||||||
mod predicate_value;
|
mod predicate_value;
|
||||||
|
537
packages/hurl_core/src/parser/multiline.rs
Normal file
537
packages/hurl_core/src/parser/multiline.rs
Normal file
@ -0,0 +1,537 @@
|
|||||||
|
/*
|
||||||
|
* Hurl (https://hurl.dev)
|
||||||
|
* Copyright (C) 2022 Orange
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
use super::combinators::*;
|
||||||
|
use super::reader::Reader;
|
||||||
|
use super::ParseResult;
|
||||||
|
use crate::ast::*;
|
||||||
|
use crate::parser::primitives::*;
|
||||||
|
use crate::parser::{template, Error, ParseError};
|
||||||
|
|
||||||
|
pub fn multiline_string(reader: &mut Reader) -> ParseResult<'static, RawString> {
|
||||||
|
try_literal("```", reader)?;
|
||||||
|
let save = reader.state.clone();
|
||||||
|
|
||||||
|
match choice(
|
||||||
|
&[
|
||||||
|
base64_lang,
|
||||||
|
hex_lang,
|
||||||
|
json_lang,
|
||||||
|
xml_lang,
|
||||||
|
graphql_lang,
|
||||||
|
undefined_lang,
|
||||||
|
],
|
||||||
|
reader,
|
||||||
|
) {
|
||||||
|
Ok(lang) => {
|
||||||
|
let value = multiline_string_value(reader)?;
|
||||||
|
Ok(RawString {
|
||||||
|
value,
|
||||||
|
lang: Some(lang),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
reader.state = save;
|
||||||
|
let value = oneline_string_value(reader)?;
|
||||||
|
Ok(RawString { value, lang: None })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn multiline_string_value(reader: &mut Reader) -> ParseResult<'static, Template> {
|
||||||
|
let mut chars = vec![];
|
||||||
|
|
||||||
|
let start = reader.state.pos.clone();
|
||||||
|
while !reader.remaining().starts_with("```") && !reader.is_eof() {
|
||||||
|
let pos = reader.state.pos.clone();
|
||||||
|
let c = reader.read().unwrap();
|
||||||
|
chars.push((c, c.to_string(), pos));
|
||||||
|
}
|
||||||
|
let end = reader.state.pos.clone();
|
||||||
|
literal("```", reader)?;
|
||||||
|
|
||||||
|
let encoded_string = template::EncodedString {
|
||||||
|
source_info: SourceInfo {
|
||||||
|
start: start.clone(),
|
||||||
|
end: end.clone(),
|
||||||
|
},
|
||||||
|
chars,
|
||||||
|
};
|
||||||
|
|
||||||
|
let elements = template::templatize(encoded_string)?;
|
||||||
|
|
||||||
|
Ok(Template {
|
||||||
|
quotes: false,
|
||||||
|
elements,
|
||||||
|
source_info: SourceInfo { start, end },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn oneline_string_value(reader: &mut Reader) -> ParseResult<'static, Template> {
|
||||||
|
let mut chars = vec![];
|
||||||
|
|
||||||
|
let start = reader.state.pos.clone();
|
||||||
|
while !reader.remaining().starts_with("```") && !reader.is_eof() {
|
||||||
|
let pos = reader.state.pos.clone();
|
||||||
|
let c = reader.read().unwrap();
|
||||||
|
if c == '\n' {
|
||||||
|
return Err(Error {
|
||||||
|
pos: start,
|
||||||
|
recoverable: false,
|
||||||
|
inner: ParseError::Multiline,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
chars.push((c, c.to_string(), pos));
|
||||||
|
}
|
||||||
|
let end = reader.state.pos.clone();
|
||||||
|
literal("```", reader)?;
|
||||||
|
|
||||||
|
let encoded_string = template::EncodedString {
|
||||||
|
source_info: SourceInfo {
|
||||||
|
start: start.clone(),
|
||||||
|
end: end.clone(),
|
||||||
|
},
|
||||||
|
chars,
|
||||||
|
};
|
||||||
|
|
||||||
|
let elements = template::templatize(encoded_string)?;
|
||||||
|
|
||||||
|
Ok(Template {
|
||||||
|
quotes: false,
|
||||||
|
elements,
|
||||||
|
source_info: SourceInfo { start, end },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn undefined_lang(reader: &mut Reader) -> ParseResult<'static, Lang> {
|
||||||
|
let space = zero_or_more_spaces(reader)?;
|
||||||
|
let newline = newline(reader)?;
|
||||||
|
Ok(Lang {
|
||||||
|
value: None,
|
||||||
|
space,
|
||||||
|
newline,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn base64_lang(reader: &mut Reader) -> ParseResult<'static, Lang> {
|
||||||
|
try_literal("base64", reader)?;
|
||||||
|
let space = zero_or_more_spaces(reader)?;
|
||||||
|
let newline = newline(reader)?;
|
||||||
|
Ok(Lang {
|
||||||
|
value: Some(LangValue::Base64),
|
||||||
|
space,
|
||||||
|
newline,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hex_lang(reader: &mut Reader) -> ParseResult<'static, Lang> {
|
||||||
|
try_literal("hex", reader)?;
|
||||||
|
let space = zero_or_more_spaces(reader)?;
|
||||||
|
let newline = newline(reader)?;
|
||||||
|
Ok(Lang {
|
||||||
|
value: Some(LangValue::Hex),
|
||||||
|
space,
|
||||||
|
newline,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn json_lang(reader: &mut Reader) -> ParseResult<'static, Lang> {
|
||||||
|
try_literal("json", reader)?;
|
||||||
|
let space = zero_or_more_spaces(reader)?;
|
||||||
|
let newline = newline(reader)?;
|
||||||
|
Ok(Lang {
|
||||||
|
value: Some(LangValue::Json),
|
||||||
|
space,
|
||||||
|
newline,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn xml_lang(reader: &mut Reader) -> ParseResult<'static, Lang> {
|
||||||
|
try_literal("xml", reader)?;
|
||||||
|
let space = zero_or_more_spaces(reader)?;
|
||||||
|
let newline = newline(reader)?;
|
||||||
|
Ok(Lang {
|
||||||
|
value: Some(LangValue::Xml),
|
||||||
|
space,
|
||||||
|
newline,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn graphql_lang(reader: &mut Reader) -> ParseResult<'static, Lang> {
|
||||||
|
try_literal("graphql", reader)?;
|
||||||
|
let space = zero_or_more_spaces(reader)?;
|
||||||
|
let newline = newline(reader)?;
|
||||||
|
Ok(Lang {
|
||||||
|
value: Some(LangValue::GraphQl),
|
||||||
|
space,
|
||||||
|
newline,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_base64_multiline_string_type() {
|
||||||
|
let mut reader = Reader::init("base64\nxxxx");
|
||||||
|
assert_eq!(
|
||||||
|
base64_lang(&mut reader).unwrap(),
|
||||||
|
Lang {
|
||||||
|
value: Some(LangValue::Base64),
|
||||||
|
space: Whitespace {
|
||||||
|
value: String::from(""),
|
||||||
|
source_info: SourceInfo::new(1, 7, 1, 7),
|
||||||
|
},
|
||||||
|
newline: Whitespace {
|
||||||
|
value: "\n".to_string(),
|
||||||
|
source_info: SourceInfo::new(1, 7, 2, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_base64_multiline_string_type_with_padding() {
|
||||||
|
let mut reader = Reader::init("base64 \nxxxx");
|
||||||
|
assert_eq!(
|
||||||
|
base64_lang(&mut reader).unwrap(),
|
||||||
|
Lang {
|
||||||
|
value: Some(LangValue::Base64),
|
||||||
|
space: Whitespace {
|
||||||
|
value: String::from(" "),
|
||||||
|
source_info: SourceInfo::new(1, 7, 1, 13),
|
||||||
|
},
|
||||||
|
newline: Whitespace {
|
||||||
|
value: "\n".to_string(),
|
||||||
|
source_info: SourceInfo::new(1, 13, 2, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_multiline_string_ok() {
|
||||||
|
let datas = [
|
||||||
|
(
|
||||||
|
"```\nline1\nline2\nline3\n```",
|
||||||
|
None,
|
||||||
|
"line1\nline2\nline3\n",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"``` \nline1\nline2\nline3\n```",
|
||||||
|
None,
|
||||||
|
"line1\nline2\nline3\n",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"```base64\nline1\nline2\nline3\n```",
|
||||||
|
Some(LangValue::Base64),
|
||||||
|
"line1\nline2\nline3\n",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"```hex\nline1\nline2\nline3\n```",
|
||||||
|
Some(LangValue::Hex),
|
||||||
|
"line1\nline2\nline3\n",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"```json\nline1\nline2\nline3\n```",
|
||||||
|
Some(LangValue::Json),
|
||||||
|
"line1\nline2\nline3\n",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"```graphql\nline1\nline2\nline3\n```",
|
||||||
|
Some(LangValue::GraphQl),
|
||||||
|
"line1\nline2\nline3\n",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"```graphql \nline1\nline2\nline3\n```",
|
||||||
|
Some(LangValue::GraphQl),
|
||||||
|
"line1\nline2\nline3\n",
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (text, lang, value) in datas.iter() {
|
||||||
|
let mut reader = Reader::init(text);
|
||||||
|
let multiline = multiline_string(&mut reader).unwrap();
|
||||||
|
assert_eq!(multiline.lang.unwrap().value, *lang);
|
||||||
|
assert_eq!(multiline.value.elements[0].to_string(), value.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_multiline_string_failed() {
|
||||||
|
let datas = [
|
||||||
|
"```hexaaa\nline1\nline2\nline3\n```",
|
||||||
|
"```aaa\nline1\nline2\nline3\n```",
|
||||||
|
];
|
||||||
|
|
||||||
|
for text in datas.iter() {
|
||||||
|
let mut reader = Reader::init(text);
|
||||||
|
assert!(multiline_string(&mut reader).is_err())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_multiline_string_empty() {
|
||||||
|
let mut reader = Reader::init("``````");
|
||||||
|
assert_eq!(
|
||||||
|
multiline_string(&mut reader).unwrap(),
|
||||||
|
RawString {
|
||||||
|
lang: None,
|
||||||
|
value: Template {
|
||||||
|
quotes: false,
|
||||||
|
elements: vec![],
|
||||||
|
source_info: SourceInfo::new(1, 4, 1, 4),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut reader = Reader::init("```\n```");
|
||||||
|
assert_eq!(
|
||||||
|
multiline_string(&mut reader).unwrap(),
|
||||||
|
RawString {
|
||||||
|
lang: Some(Lang {
|
||||||
|
value: None,
|
||||||
|
space: Whitespace {
|
||||||
|
value: "".to_string(),
|
||||||
|
source_info: SourceInfo::new(1, 4, 1, 4)
|
||||||
|
},
|
||||||
|
newline: Whitespace {
|
||||||
|
value: "\n".to_string(),
|
||||||
|
source_info: SourceInfo::new(1, 4, 2, 1)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
value: Template {
|
||||||
|
quotes: false,
|
||||||
|
elements: vec![],
|
||||||
|
source_info: SourceInfo::new(2, 1, 2, 1),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
let mut reader = Reader::init("```\r\n```");
|
||||||
|
assert_eq!(
|
||||||
|
multiline_string(&mut reader).unwrap(),
|
||||||
|
RawString {
|
||||||
|
lang: Some(Lang {
|
||||||
|
value: None,
|
||||||
|
space: Whitespace {
|
||||||
|
value: "".to_string(),
|
||||||
|
source_info: SourceInfo::new(1, 4, 1, 4)
|
||||||
|
},
|
||||||
|
newline: Whitespace {
|
||||||
|
value: "\r\n".to_string(),
|
||||||
|
source_info: SourceInfo::new(1, 4, 2, 1)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
value: Template {
|
||||||
|
quotes: false,
|
||||||
|
elements: vec![],
|
||||||
|
source_info: SourceInfo::new(2, 1, 2, 1),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_raw_string_hello() {
|
||||||
|
let mut reader = Reader::init("```Hello World!```");
|
||||||
|
assert_eq!(
|
||||||
|
multiline_string(&mut reader).unwrap(),
|
||||||
|
RawString {
|
||||||
|
lang: None,
|
||||||
|
value: Template {
|
||||||
|
quotes: false,
|
||||||
|
elements: vec![TemplateElement::String {
|
||||||
|
value: "Hello World!".to_string(),
|
||||||
|
encoded: "Hello World!".to_string(),
|
||||||
|
}],
|
||||||
|
source_info: SourceInfo::new(1, 4, 1, 16),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_raw_string_base64_prefix() {
|
||||||
|
let mut reader = Reader::init("```base64_inline```");
|
||||||
|
assert_eq!(
|
||||||
|
multiline_string(&mut reader).unwrap(),
|
||||||
|
RawString {
|
||||||
|
lang: None,
|
||||||
|
value: Template {
|
||||||
|
quotes: false,
|
||||||
|
elements: vec![TemplateElement::String {
|
||||||
|
value: "base64_inline".to_string(),
|
||||||
|
encoded: "base64_inline".to_string(),
|
||||||
|
}],
|
||||||
|
source_info: SourceInfo::new(1, 4, 1, 17),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_raw_string_csv() {
|
||||||
|
let mut reader = Reader::init("```\nline1\nline2\nline3\n```");
|
||||||
|
assert_eq!(
|
||||||
|
multiline_string(&mut reader).unwrap(),
|
||||||
|
RawString {
|
||||||
|
lang: Some(Lang {
|
||||||
|
value: None,
|
||||||
|
space: Whitespace {
|
||||||
|
value: "".to_string(),
|
||||||
|
source_info: SourceInfo::new(1, 4, 1, 4),
|
||||||
|
},
|
||||||
|
newline: Whitespace {
|
||||||
|
value: "\n".to_string(),
|
||||||
|
source_info: SourceInfo::new(1, 4, 2, 1),
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
value: Template {
|
||||||
|
quotes: false,
|
||||||
|
elements: vec![TemplateElement::String {
|
||||||
|
value: "line1\nline2\nline3\n".to_string(),
|
||||||
|
encoded: "line1\nline2\nline3\n".to_string(),
|
||||||
|
}],
|
||||||
|
source_info: SourceInfo::new(2, 1, 5, 1),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_raw_string_one_emptyline() {
|
||||||
|
// one newline
|
||||||
|
// the value takes the value of the newline??
|
||||||
|
let mut reader = Reader::init("```\n\n```");
|
||||||
|
assert_eq!(
|
||||||
|
multiline_string(&mut reader).unwrap(),
|
||||||
|
RawString {
|
||||||
|
lang: Some(Lang {
|
||||||
|
value: None,
|
||||||
|
space: Whitespace {
|
||||||
|
value: "".to_string(),
|
||||||
|
source_info: SourceInfo::new(1, 4, 1, 4),
|
||||||
|
},
|
||||||
|
newline: Whitespace {
|
||||||
|
value: "\n".to_string(),
|
||||||
|
source_info: SourceInfo::new(1, 4, 2, 1),
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
value: Template {
|
||||||
|
quotes: false,
|
||||||
|
elements: vec![TemplateElement::String {
|
||||||
|
value: "\n".to_string(),
|
||||||
|
encoded: "\n".to_string(),
|
||||||
|
}],
|
||||||
|
source_info: SourceInfo::new(2, 1, 3, 1),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// one cr
|
||||||
|
let mut reader = Reader::init("```\n\r\n````");
|
||||||
|
assert_eq!(
|
||||||
|
multiline_string(&mut reader).unwrap(),
|
||||||
|
RawString {
|
||||||
|
lang: Some(Lang {
|
||||||
|
value: None,
|
||||||
|
space: Whitespace {
|
||||||
|
value: "".to_string(),
|
||||||
|
source_info: SourceInfo::new(1, 4, 1, 4),
|
||||||
|
},
|
||||||
|
newline: Whitespace {
|
||||||
|
value: "\n".to_string(),
|
||||||
|
source_info: SourceInfo::new(1, 4, 2, 1),
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
value: Template {
|
||||||
|
quotes: false,
|
||||||
|
elements: vec![TemplateElement::String {
|
||||||
|
value: "\r\n".to_string(),
|
||||||
|
encoded: "\r\n".to_string(),
|
||||||
|
}],
|
||||||
|
source_info: SourceInfo::new(2, 1, 3, 1),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_raw_string_error() {
|
||||||
|
let mut reader = Reader::init("xxx");
|
||||||
|
let error = multiline_string(&mut reader).err().unwrap();
|
||||||
|
assert_eq!(error.pos, Pos { line: 1, column: 1 });
|
||||||
|
assert_eq!(
|
||||||
|
error.inner,
|
||||||
|
ParseError::Expecting {
|
||||||
|
value: String::from("```")
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assert!(error.recoverable);
|
||||||
|
|
||||||
|
let mut reader = Reader::init("```\nxxx");
|
||||||
|
let error = multiline_string(&mut reader).err().unwrap();
|
||||||
|
assert_eq!(error.pos, Pos { line: 2, column: 4 });
|
||||||
|
assert_eq!(
|
||||||
|
error.inner,
|
||||||
|
ParseError::Expecting {
|
||||||
|
value: String::from("```")
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assert!(!error.recoverable);
|
||||||
|
|
||||||
|
let mut reader = Reader::init("```xxx");
|
||||||
|
let error = multiline_string(&mut reader).err().unwrap();
|
||||||
|
assert_eq!(error.pos, Pos { line: 1, column: 7 });
|
||||||
|
assert_eq!(
|
||||||
|
error.inner,
|
||||||
|
ParseError::Expecting {
|
||||||
|
value: String::from("```")
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assert!(!error.recoverable);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_raw_string_value() {
|
||||||
|
let mut reader = Reader::init("```");
|
||||||
|
assert_eq!(
|
||||||
|
multiline_string_value(&mut reader).unwrap(),
|
||||||
|
Template {
|
||||||
|
quotes: false,
|
||||||
|
elements: vec![],
|
||||||
|
source_info: SourceInfo::new(1, 1, 1, 1),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assert_eq!(reader.state.cursor, 3);
|
||||||
|
|
||||||
|
let mut reader = Reader::init("hello```");
|
||||||
|
assert_eq!(
|
||||||
|
multiline_string_value(&mut reader).unwrap(),
|
||||||
|
Template {
|
||||||
|
quotes: false,
|
||||||
|
elements: vec![TemplateElement::String {
|
||||||
|
value: "hello".to_string(),
|
||||||
|
encoded: "hello".to_string(),
|
||||||
|
}],
|
||||||
|
source_info: SourceInfo::new(1, 1, 1, 6),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assert_eq!(reader.state.cursor, 8);
|
||||||
|
}
|
||||||
|
}
|
@ -407,10 +407,17 @@ mod tests {
|
|||||||
source_info: SourceInfo::new(2, 1, 2, 1),
|
source_info: SourceInfo::new(2, 1, 2, 1),
|
||||||
},
|
},
|
||||||
value: Bytes::RawString(RawString {
|
value: Bytes::RawString(RawString {
|
||||||
newline: Whitespace {
|
lang: Some(Lang {
|
||||||
value: "\n".to_string(),
|
value: None,
|
||||||
source_info: SourceInfo::new(2, 4, 3, 1),
|
space: Whitespace {
|
||||||
},
|
value: "".to_string(),
|
||||||
|
source_info: SourceInfo::new(2, 4, 2, 4),
|
||||||
|
},
|
||||||
|
newline: Whitespace {
|
||||||
|
source_info: SourceInfo::new(2, 4, 3, 1),
|
||||||
|
value: "\n".to_string(),
|
||||||
|
}
|
||||||
|
}),
|
||||||
value: Template {
|
value: Template {
|
||||||
elements: vec![TemplateElement::String {
|
elements: vec![TemplateElement::String {
|
||||||
value: String::from("Hello World!\n"),
|
value: String::from("Hello World!\n"),
|
||||||
|
@ -24,6 +24,7 @@ use super::primitives::*;
|
|||||||
use super::reader::Reader;
|
use super::reader::Reader;
|
||||||
use super::string::*;
|
use super::string::*;
|
||||||
use super::ParseResult;
|
use super::ParseResult;
|
||||||
|
use crate::parser::multiline::multiline_string;
|
||||||
use crate::parser::{Error, ParseError};
|
use crate::parser::{Error, ParseError};
|
||||||
|
|
||||||
pub fn predicate_value(reader: &mut Reader) -> ParseResult<'static, PredicateValue> {
|
pub fn predicate_value(reader: &mut Reader) -> ParseResult<'static, PredicateValue> {
|
||||||
@ -61,7 +62,7 @@ pub fn predicate_value(reader: &mut Reader) -> ParseResult<'static, PredicateVal
|
|||||||
Ok(value) => Ok(PredicateValue::String(value)),
|
Ok(value) => Ok(PredicateValue::String(value)),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
},
|
},
|
||||||
|p1| match raw_string(p1) {
|
|p1| match multiline_string(p1) {
|
||||||
Ok(value) => Ok(PredicateValue::Raw(value)),
|
Ok(value) => Ok(PredicateValue::Raw(value)),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
},
|
},
|
||||||
|
@ -23,7 +23,6 @@ use super::error::*;
|
|||||||
use super::filename;
|
use super::filename;
|
||||||
use super::reader::Reader;
|
use super::reader::Reader;
|
||||||
use super::string::*;
|
use super::string::*;
|
||||||
use super::template;
|
|
||||||
use super::ParseResult;
|
use super::ParseResult;
|
||||||
|
|
||||||
pub fn space(reader: &mut Reader) -> ParseResult<'static, Whitespace> {
|
pub fn space(reader: &mut Reader) -> ParseResult<'static, Whitespace> {
|
||||||
@ -502,60 +501,6 @@ pub fn float(reader: &mut Reader) -> ParseResult<'static, Float> {
|
|||||||
Ok(Float { value, encoded })
|
Ok(Float { value, encoded })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn raw_string(reader: &mut Reader) -> ParseResult<'static, RawString> {
|
|
||||||
// one value without newline or multiline mode
|
|
||||||
// includes the last newline (consistent with bash EOL)
|
|
||||||
try_literal("```", reader)?;
|
|
||||||
let save = reader.state.clone();
|
|
||||||
match newline(reader) {
|
|
||||||
Ok(newline) => {
|
|
||||||
let value = raw_string_value(reader)?;
|
|
||||||
Ok(RawString { newline, value })
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
reader.state = save;
|
|
||||||
let newline = Whitespace {
|
|
||||||
value: String::from(""),
|
|
||||||
source_info: SourceInfo {
|
|
||||||
start: reader.state.clone().pos,
|
|
||||||
end: reader.state.clone().pos,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
let value = raw_string_value(reader)?;
|
|
||||||
Ok(RawString { newline, value })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn raw_string_value(reader: &mut Reader) -> ParseResult<'static, Template> {
|
|
||||||
let mut chars = vec![];
|
|
||||||
|
|
||||||
let start = reader.state.pos.clone();
|
|
||||||
while !reader.remaining().starts_with("```") && !reader.is_eof() {
|
|
||||||
let pos = reader.state.pos.clone();
|
|
||||||
let c = reader.read().unwrap();
|
|
||||||
chars.push((c, c.to_string(), pos));
|
|
||||||
}
|
|
||||||
let end = reader.state.pos.clone();
|
|
||||||
literal("```", reader)?;
|
|
||||||
|
|
||||||
let encoded_string = template::EncodedString {
|
|
||||||
source_info: SourceInfo {
|
|
||||||
start: start.clone(),
|
|
||||||
end: end.clone(),
|
|
||||||
},
|
|
||||||
chars,
|
|
||||||
};
|
|
||||||
|
|
||||||
let elements = template::templatize(encoded_string)?;
|
|
||||||
|
|
||||||
Ok(Template {
|
|
||||||
quotes: false,
|
|
||||||
elements,
|
|
||||||
source_info: SourceInfo { start, end },
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn file(reader: &mut Reader) -> ParseResult<'static, File> {
|
pub(crate) fn file(reader: &mut Reader) -> ParseResult<'static, File> {
|
||||||
let _start = reader.state.clone();
|
let _start = reader.state.clone();
|
||||||
try_literal("file", reader)?;
|
try_literal("file", reader)?;
|
||||||
@ -1120,226 +1065,6 @@ mod tests {
|
|||||||
assert!(!error.recoverable);
|
assert!(!error.recoverable);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_raw_string_empty() {
|
|
||||||
let mut reader = Reader::init("``````");
|
|
||||||
assert_eq!(
|
|
||||||
raw_string(&mut reader).unwrap(),
|
|
||||||
RawString {
|
|
||||||
newline: Whitespace {
|
|
||||||
value: String::from(""),
|
|
||||||
source_info: SourceInfo::new(1, 4, 1, 4),
|
|
||||||
},
|
|
||||||
value: Template {
|
|
||||||
quotes: false,
|
|
||||||
elements: vec![],
|
|
||||||
source_info: SourceInfo::new(1, 4, 1, 4),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut reader = Reader::init("```\n```");
|
|
||||||
assert_eq!(
|
|
||||||
raw_string(&mut reader).unwrap(),
|
|
||||||
RawString {
|
|
||||||
newline: Whitespace {
|
|
||||||
value: String::from("\n"),
|
|
||||||
source_info: SourceInfo::new(1, 4, 2, 1),
|
|
||||||
},
|
|
||||||
value: Template {
|
|
||||||
quotes: false,
|
|
||||||
elements: vec![],
|
|
||||||
source_info: SourceInfo::new(2, 1, 2, 1),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
let mut reader = Reader::init("```\r\n```");
|
|
||||||
assert_eq!(
|
|
||||||
raw_string(&mut reader).unwrap(),
|
|
||||||
RawString {
|
|
||||||
newline: Whitespace {
|
|
||||||
value: String::from("\r\n"),
|
|
||||||
source_info: SourceInfo::new(1, 4, 2, 1),
|
|
||||||
},
|
|
||||||
value: Template {
|
|
||||||
quotes: false,
|
|
||||||
elements: vec![],
|
|
||||||
source_info: SourceInfo::new(2, 1, 2, 1),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_raw_string_hello() {
|
|
||||||
let mut reader = Reader::init("```Hello World!```");
|
|
||||||
assert_eq!(
|
|
||||||
raw_string(&mut reader).unwrap(),
|
|
||||||
RawString {
|
|
||||||
newline: Whitespace {
|
|
||||||
value: String::from(""),
|
|
||||||
source_info: SourceInfo::new(1, 4, 1, 4),
|
|
||||||
},
|
|
||||||
value: Template {
|
|
||||||
quotes: false,
|
|
||||||
elements: vec![TemplateElement::String {
|
|
||||||
value: "Hello World!".to_string(),
|
|
||||||
encoded: "Hello World!".to_string(),
|
|
||||||
}],
|
|
||||||
source_info: SourceInfo::new(1, 4, 1, 16),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
let mut reader = Reader::init("```Hello\nWorld!\n```");
|
|
||||||
assert_eq!(
|
|
||||||
raw_string(&mut reader).unwrap(),
|
|
||||||
RawString {
|
|
||||||
newline: Whitespace {
|
|
||||||
value: String::from(""),
|
|
||||||
source_info: SourceInfo::new(1, 4, 1, 4),
|
|
||||||
},
|
|
||||||
value: Template {
|
|
||||||
quotes: false,
|
|
||||||
elements: vec![TemplateElement::String {
|
|
||||||
value: "Hello\nWorld!\n".to_string(),
|
|
||||||
encoded: "Hello\nWorld!\n".to_string(),
|
|
||||||
}],
|
|
||||||
source_info: SourceInfo::new(1, 4, 3, 1),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_raw_string_csv() {
|
|
||||||
let mut reader = Reader::init("```\nline1\nline2\nline3\n```");
|
|
||||||
assert_eq!(
|
|
||||||
raw_string(&mut reader).unwrap(),
|
|
||||||
RawString {
|
|
||||||
newline: Whitespace {
|
|
||||||
value: String::from("\n"),
|
|
||||||
source_info: SourceInfo::new(1, 4, 2, 1),
|
|
||||||
},
|
|
||||||
value: Template {
|
|
||||||
quotes: false,
|
|
||||||
elements: vec![TemplateElement::String {
|
|
||||||
value: "line1\nline2\nline3\n".to_string(),
|
|
||||||
encoded: "line1\nline2\nline3\n".to_string(),
|
|
||||||
}],
|
|
||||||
source_info: SourceInfo::new(2, 1, 5, 1),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_raw_string_one_emptyline() {
|
|
||||||
// one newline
|
|
||||||
// the value takes the value of the newline??
|
|
||||||
let mut reader = Reader::init("```\n\n```");
|
|
||||||
assert_eq!(
|
|
||||||
raw_string(&mut reader).unwrap(),
|
|
||||||
RawString {
|
|
||||||
newline: Whitespace {
|
|
||||||
value: String::from("\n"),
|
|
||||||
source_info: SourceInfo::new(1, 4, 2, 1),
|
|
||||||
},
|
|
||||||
value: Template {
|
|
||||||
quotes: false,
|
|
||||||
elements: vec![TemplateElement::String {
|
|
||||||
value: "\n".to_string(),
|
|
||||||
encoded: "\n".to_string(),
|
|
||||||
}],
|
|
||||||
source_info: SourceInfo::new(2, 1, 3, 1),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// one cr
|
|
||||||
let mut reader = Reader::init("```\n\r\n````");
|
|
||||||
assert_eq!(
|
|
||||||
raw_string(&mut reader).unwrap(),
|
|
||||||
RawString {
|
|
||||||
newline: Whitespace {
|
|
||||||
value: String::from("\n"),
|
|
||||||
source_info: SourceInfo::new(1, 4, 2, 1),
|
|
||||||
},
|
|
||||||
value: Template {
|
|
||||||
quotes: false,
|
|
||||||
elements: vec![TemplateElement::String {
|
|
||||||
value: "\r\n".to_string(),
|
|
||||||
encoded: "\r\n".to_string(),
|
|
||||||
}],
|
|
||||||
source_info: SourceInfo::new(2, 1, 3, 1),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_raw_string_error() {
|
|
||||||
let mut reader = Reader::init("xxx");
|
|
||||||
let error = raw_string(&mut reader).err().unwrap();
|
|
||||||
assert_eq!(error.pos, Pos { line: 1, column: 1 });
|
|
||||||
assert_eq!(
|
|
||||||
error.inner,
|
|
||||||
ParseError::Expecting {
|
|
||||||
value: String::from("```")
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert!(error.recoverable);
|
|
||||||
|
|
||||||
let mut reader = Reader::init("```\nxxx");
|
|
||||||
let error = raw_string(&mut reader).err().unwrap();
|
|
||||||
assert_eq!(error.pos, Pos { line: 2, column: 4 });
|
|
||||||
assert_eq!(
|
|
||||||
error.inner,
|
|
||||||
ParseError::Expecting {
|
|
||||||
value: String::from("```")
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert!(!error.recoverable);
|
|
||||||
|
|
||||||
let mut reader = Reader::init("```xxx");
|
|
||||||
let error = raw_string(&mut reader).err().unwrap();
|
|
||||||
assert_eq!(error.pos, Pos { line: 1, column: 7 });
|
|
||||||
assert_eq!(
|
|
||||||
error.inner,
|
|
||||||
ParseError::Expecting {
|
|
||||||
value: String::from("```")
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert!(!error.recoverable);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_raw_string_value() {
|
|
||||||
let mut reader = Reader::init("```");
|
|
||||||
assert_eq!(
|
|
||||||
raw_string_value(&mut reader).unwrap(),
|
|
||||||
Template {
|
|
||||||
quotes: false,
|
|
||||||
elements: vec![],
|
|
||||||
source_info: SourceInfo::new(1, 1, 1, 1),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(reader.state.cursor, 3);
|
|
||||||
|
|
||||||
let mut reader = Reader::init("hello```");
|
|
||||||
assert_eq!(
|
|
||||||
raw_string_value(&mut reader).unwrap(),
|
|
||||||
Template {
|
|
||||||
quotes: false,
|
|
||||||
elements: vec![TemplateElement::String {
|
|
||||||
value: "hello".to_string(),
|
|
||||||
encoded: "hello".to_string(),
|
|
||||||
}],
|
|
||||||
source_info: SourceInfo::new(1, 1, 1, 6),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(reader.state.cursor, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_hex_digit() {
|
fn test_hex_digit() {
|
||||||
let mut reader = Reader::init("0");
|
let mut reader = Reader::init("0");
|
||||||
|
@ -141,10 +141,20 @@ impl ToJson for Bytes {
|
|||||||
("type".to_string(), JValue::String("xml".to_string())),
|
("type".to_string(), JValue::String("xml".to_string())),
|
||||||
("value".to_string(), JValue::String(value.clone())),
|
("value".to_string(), JValue::String(value.clone())),
|
||||||
]),
|
]),
|
||||||
Bytes::RawString(value) => JValue::Object(vec![
|
Bytes::RawString(value) => {
|
||||||
("type".to_string(), JValue::String("raw-string".to_string())),
|
let lang = match &value.lang {
|
||||||
("value".to_string(), JValue::String(value.value.to_string())),
|
// TODO: change raw-string for undefined
|
||||||
]),
|
None | Some(Lang { value: None, .. }) => "raw-string".to_string(),
|
||||||
|
Some(Lang {
|
||||||
|
value: Some(lang_value),
|
||||||
|
..
|
||||||
|
}) => lang_value.to_string(),
|
||||||
|
};
|
||||||
|
JValue::Object(vec![
|
||||||
|
("type".to_string(), JValue::String(lang)),
|
||||||
|
("value".to_string(), JValue::String(value.value.to_string())),
|
||||||
|
])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,5 +121,6 @@ pub fn format_token(token: Token, color: bool) -> String {
|
|||||||
value
|
value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Token::Lang(value) => value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ pub enum Token {
|
|||||||
String(String),
|
String(String),
|
||||||
CodeDelimiter(String),
|
CodeDelimiter(String),
|
||||||
CodeVariable(String),
|
CodeVariable(String),
|
||||||
|
Lang(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Tokenizable {
|
pub trait Tokenizable {
|
||||||
@ -605,16 +606,35 @@ impl Tokenizable for PredicateValue {
|
|||||||
|
|
||||||
impl Tokenizable for RawString {
|
impl Tokenizable for RawString {
|
||||||
fn tokenize(&self) -> Vec<Token> {
|
fn tokenize(&self) -> Vec<Token> {
|
||||||
let mut tokens: Vec<Token> = vec![
|
let mut tokens: Vec<Token> = vec![Token::Keyword("```".to_string())];
|
||||||
Token::Keyword("```".to_string()),
|
if let Some(kind) = &self.lang {
|
||||||
Token::Whitespace(self.newline.value.clone()),
|
tokens.append(&mut kind.tokenize())
|
||||||
];
|
}
|
||||||
tokens.append(&mut self.value.tokenize());
|
tokens.append(&mut self.value.tokenize());
|
||||||
tokens.push(Token::Keyword("```".to_string()));
|
tokens.push(Token::Keyword("```".to_string()));
|
||||||
tokens
|
tokens
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Tokenizable for Lang {
|
||||||
|
fn tokenize(&self) -> Vec<Token> {
|
||||||
|
let mut tokens: Vec<Token> = vec![];
|
||||||
|
if let Some(value) = &self.value {
|
||||||
|
tokens.append(&mut value.tokenize());
|
||||||
|
}
|
||||||
|
tokens.append(&mut self.space.tokenize());
|
||||||
|
tokens.append(&mut self.newline.tokenize());
|
||||||
|
tokens
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tokenizable for LangValue {
|
||||||
|
fn tokenize(&self) -> Vec<Token> {
|
||||||
|
let token = Token::Lang(self.to_string());
|
||||||
|
vec![token]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Tokenizable for EncodedString {
|
impl Tokenizable for EncodedString {
|
||||||
fn tokenize(&self) -> Vec<Token> {
|
fn tokenize(&self) -> Vec<Token> {
|
||||||
let mut tokens: Vec<Token> = vec![];
|
let mut tokens: Vec<Token> = vec![];
|
||||||
|
@ -520,7 +520,7 @@ impl Lintable<RawString> for RawString {
|
|||||||
|
|
||||||
fn lint(&self) -> RawString {
|
fn lint(&self) -> RawString {
|
||||||
RawString {
|
RawString {
|
||||||
newline: self.newline.clone(),
|
lang: None,
|
||||||
value: self.value.lint(),
|
value: self.value.lint(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user