@tishlang/tish 1.0.11 → 1.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/crates/tish/Cargo.toml +1 -1
- package/crates/tish/src/main.rs +1 -0
- package/crates/tish/tests/integration_test.rs +20 -0
- package/crates/tish_compile_js/src/tests_jsx.rs +51 -1
- package/crates/tish_jsx_web/vendor/Lattish.tish +15 -0
- package/crates/tish_parser/src/parser.rs +21 -3
- package/package.json +1 -1
- package/platform/darwin-arm64/tish +0 -0
- package/platform/darwin-x64/tish +0 -0
- package/platform/linux-arm64/tish +0 -0
- package/platform/linux-x64/tish +0 -0
- package/platform/win32-x64/tish.exe +0 -0
package/crates/tish/Cargo.toml
CHANGED
package/crates/tish/src/main.rs
CHANGED
|
@@ -14,6 +14,7 @@ use rustyline::{Behavior, ColorMode, CompletionType, Config, Editor};
|
|
|
14
14
|
#[derive(Parser)]
|
|
15
15
|
#[command(name = "tish")]
|
|
16
16
|
#[command(about = "Tish - minimal TS/JS-compatible language")]
|
|
17
|
+
#[command(version = env!("CARGO_PKG_VERSION"))]
|
|
17
18
|
#[command(after_help = "To disable optimizations: TISH_NO_OPTIMIZE=1")]
|
|
18
19
|
pub(crate) struct Cli {
|
|
19
20
|
#[command(subcommand)]
|
|
@@ -163,6 +163,26 @@ fn tish_bin() -> PathBuf {
|
|
|
163
163
|
default
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
+
/// tish -V and --version print the version.
|
|
167
|
+
#[test]
|
|
168
|
+
fn test_tish_version_flag() {
|
|
169
|
+
let bin = tish_bin();
|
|
170
|
+
assert!(bin.exists(), "tish binary not found. Run `cargo build -p tish` first.");
|
|
171
|
+
let out = Command::new(&bin).arg("-V").output().expect("run tish -V");
|
|
172
|
+
assert!(out.status.success(), "tish -V failed: {}", String::from_utf8_lossy(&out.stderr));
|
|
173
|
+
let stdout = String::from_utf8_lossy(&out.stdout);
|
|
174
|
+
assert!(
|
|
175
|
+
stdout.contains(env!("CARGO_PKG_VERSION")),
|
|
176
|
+
"tish -V should print version {}; got: {}",
|
|
177
|
+
env!("CARGO_PKG_VERSION"),
|
|
178
|
+
stdout
|
|
179
|
+
);
|
|
180
|
+
let out2 = Command::new(&bin).arg("--version").output().expect("run tish --version");
|
|
181
|
+
assert!(out2.status.success());
|
|
182
|
+
let stdout2 = String::from_utf8_lossy(&out2.stdout);
|
|
183
|
+
assert!(stdout2.contains(env!("CARGO_PKG_VERSION")), "tish --version should print version");
|
|
184
|
+
}
|
|
185
|
+
|
|
166
186
|
/// Parse async-await example (validates async fn parsing).
|
|
167
187
|
#[test]
|
|
168
188
|
fn test_async_await_parse() {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
#[cfg(test)]
|
|
2
2
|
mod tests {
|
|
3
|
+
use std::io::Write;
|
|
4
|
+
|
|
3
5
|
use tish_parser::parse;
|
|
4
6
|
|
|
5
|
-
use crate::{compile_with_jsx, JsxMode};
|
|
7
|
+
use crate::{compile_project_with_jsx, compile_with_jsx, JsxMode};
|
|
6
8
|
|
|
7
9
|
#[test]
|
|
8
10
|
fn lattish_jsx_emits_h_with_children_array() {
|
|
@@ -21,6 +23,54 @@ mod tests {
|
|
|
21
23
|
assert!(js.contains("h(Fragment, null, ["));
|
|
22
24
|
}
|
|
23
25
|
|
|
26
|
+
#[test]
|
|
27
|
+
fn jsx_text_whitespace_coalesced() {
|
|
28
|
+
let src = r#"fn X() { return <p>First paragraph</p> }"#;
|
|
29
|
+
let program = parse(src).unwrap();
|
|
30
|
+
let js = compile_with_jsx(&program, false, JsxMode::LattishH).unwrap();
|
|
31
|
+
assert!(
|
|
32
|
+
js.contains("\"First paragraph\""),
|
|
33
|
+
"expected \"First paragraph\" in output, got: {}",
|
|
34
|
+
&js[..400.min(js.len())]
|
|
35
|
+
);
|
|
36
|
+
assert!(
|
|
37
|
+
!js.contains("\"First\", \"paragraph\""),
|
|
38
|
+
"text should be coalesced, not split"
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
#[test]
|
|
43
|
+
fn jsx_text_whitespace_coalesced_multiline() {
|
|
44
|
+
let src = "fn App() {\n return <p>First paragraph</p>\n}";
|
|
45
|
+
let program = parse(src).unwrap();
|
|
46
|
+
let js = compile_with_jsx(&program, false, JsxMode::LattishH).unwrap();
|
|
47
|
+
assert!(
|
|
48
|
+
js.contains("\"First paragraph\""),
|
|
49
|
+
"multiline: expected \"First paragraph\", got: {}",
|
|
50
|
+
&js[..400.min(js.len())]
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
#[test]
|
|
55
|
+
fn jsx_text_whitespace_via_compile_project() {
|
|
56
|
+
let dir = std::env::temp_dir().join("tish_compile_project_test");
|
|
57
|
+
let _ = std::fs::create_dir_all(&dir);
|
|
58
|
+
let path = dir.join("test.tish");
|
|
59
|
+
let src = "fn App() {\n return <p>First paragraph</p>\n}";
|
|
60
|
+
let mut f = std::fs::File::create(&path).unwrap();
|
|
61
|
+
f.write_all(src.as_bytes()).unwrap();
|
|
62
|
+
f.sync_all().unwrap();
|
|
63
|
+
drop(f);
|
|
64
|
+
let js = compile_project_with_jsx(&path, Some(&dir), false, JsxMode::LattishH)
|
|
65
|
+
.expect("compile_project_with_jsx failed");
|
|
66
|
+
assert!(
|
|
67
|
+
js.contains("\"First paragraph\""),
|
|
68
|
+
"compile_project: expected \"First paragraph\", got: {}",
|
|
69
|
+
&js[..500.min(js.len())]
|
|
70
|
+
);
|
|
71
|
+
let _ = std::fs::remove_file(&path);
|
|
72
|
+
}
|
|
73
|
+
|
|
24
74
|
#[test]
|
|
25
75
|
fn vdom_emits_vdom_h() {
|
|
26
76
|
let src = r#"fn X() { return <p/> }"#;
|
|
@@ -27,6 +27,21 @@ export fn h(tag, props, children) {
|
|
|
27
27
|
if (children === undefined || children === null) {
|
|
28
28
|
children = []
|
|
29
29
|
}
|
|
30
|
+
if (typeof tag === "function") {
|
|
31
|
+
let p = props && props !== null ? props : {}
|
|
32
|
+
if (children.length > 0) {
|
|
33
|
+
let newProps = {}
|
|
34
|
+
let keys = Object.keys(p)
|
|
35
|
+
let i = 0
|
|
36
|
+
while (i < keys.length) {
|
|
37
|
+
newProps[keys[i]] = p[keys[i]]
|
|
38
|
+
i = i + 1
|
|
39
|
+
}
|
|
40
|
+
newProps.children = children
|
|
41
|
+
p = newProps
|
|
42
|
+
}
|
|
43
|
+
return tag(p)
|
|
44
|
+
}
|
|
30
45
|
if (tag === Fragment) {
|
|
31
46
|
let f = document.createDocumentFragment()
|
|
32
47
|
let i = 0
|
|
@@ -1561,6 +1561,17 @@ impl<'a> Parser<'a> {
|
|
|
1561
1561
|
})
|
|
1562
1562
|
}
|
|
1563
1563
|
|
|
1564
|
+
/// Push text child, merging with previous Text if any (preserves spaces between tokens).
|
|
1565
|
+
fn push_or_merge_text(&self, children: &mut Vec<JsxChild>, s: Arc<str>) {
|
|
1566
|
+
if let Some(JsxChild::Text(prev)) = children.last() {
|
|
1567
|
+
let merged = format!("{} {}", prev.as_ref(), s.as_ref());
|
|
1568
|
+
let last = children.len() - 1;
|
|
1569
|
+
children[last] = JsxChild::Text(Arc::from(merged.as_str()));
|
|
1570
|
+
} else {
|
|
1571
|
+
children.push(JsxChild::Text(s));
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1564
1575
|
/// Parse JSX children until </Tag> or </>
|
|
1565
1576
|
fn parse_jsx_children(&mut self, close_tag: &str) -> Result<Vec<JsxChild>, String> {
|
|
1566
1577
|
let mut children = Vec::new();
|
|
@@ -1601,7 +1612,7 @@ impl<'a> Parser<'a> {
|
|
|
1601
1612
|
let t = self.advance().unwrap();
|
|
1602
1613
|
let s = t.literal.clone().unwrap_or_default();
|
|
1603
1614
|
if !s.is_empty() {
|
|
1604
|
-
|
|
1615
|
+
self.push_or_merge_text(&mut children, s);
|
|
1605
1616
|
}
|
|
1606
1617
|
}
|
|
1607
1618
|
Some(TokenKind::Ident) => {
|
|
@@ -1609,7 +1620,7 @@ impl<'a> Parser<'a> {
|
|
|
1609
1620
|
let t = self.advance().unwrap();
|
|
1610
1621
|
let s = t.literal.clone().unwrap_or_default();
|
|
1611
1622
|
if !s.is_empty() {
|
|
1612
|
-
|
|
1623
|
+
self.push_or_merge_text(&mut children, s);
|
|
1613
1624
|
}
|
|
1614
1625
|
}
|
|
1615
1626
|
_ => {
|
|
@@ -1659,7 +1670,14 @@ impl<'a> Parser<'a> {
|
|
|
1659
1670
|
let t = self.advance().unwrap();
|
|
1660
1671
|
let s = t.literal.clone().unwrap_or_default();
|
|
1661
1672
|
if !s.is_empty() {
|
|
1662
|
-
|
|
1673
|
+
self.push_or_merge_text(&mut children, s);
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
Some(TokenKind::Ident) => {
|
|
1677
|
+
let t = self.advance().unwrap();
|
|
1678
|
+
let s = t.literal.clone().unwrap_or_default();
|
|
1679
|
+
if !s.is_empty() {
|
|
1680
|
+
self.push_or_merge_text(&mut children, s);
|
|
1663
1681
|
}
|
|
1664
1682
|
}
|
|
1665
1683
|
_ => return Err(format!("Unexpected token in JSX fragment: {:?}", self.peek_kind())),
|
package/package.json
CHANGED
|
Binary file
|
package/platform/darwin-x64/tish
CHANGED
|
Binary file
|
|
Binary file
|
package/platform/linux-x64/tish
CHANGED
|
Binary file
|
|
Binary file
|