Crates.io | ts_quote |
lib.rs | ts_quote |
version | 0.2.1 |
source | src |
created_at | 2023-11-25 16:11:47.653862 |
updated_at | 2023-11-27 16:45:30.578876 |
description | Procedural macros for quasi-quoting TypeScript from Rust |
homepage | |
repository | https://github.com/spencerkohan/type_reflect/tree/main/ts_quote |
max_upload_size | |
id | 1048401 |
size | 8,886 |
This crate is part of a larger workspace, see the monorepo README for more details
This crate provides a few quasi-quote macros for generating TypeScript from inside Rust.
It is built upon the Deno
project, and is interoperable with Deno's TypeScript representation.
The interface is heavily inspired by the popular quote
crate crate for Rust code generation.
Generate a Typescript string using ts_string!
:
let ts: String = ts_string! { const foo: number = 42; }
// the value of ts is "const foo: number = 42;"
It's also possible to embed runtime values from Rust.
This should feel familiar to anyone who has used quote
to generate Rust code:
let name = "foo";
let value: u32 = 7;
let ts: String = ts_string! { const #name: number = #{value + 1}; }
// the value of ts is "const foo: number = 8;"
Values can be included from Rust by prefixing with #
.
To include a simple value, the pattern #<identifier>
will be replaced with the value of <identifier>
.
Sometimes it's not posible to represent TypeScript syntax as a valid Rust TokenStream.
For instance, if we try to use ts_string
like so it will fail:
let ts: String = ts_string! { const text = 'some text here'; }
let ts: String = ts_string! { const text = `some other text here`; }
This is becuase 'some text here' and some other text here
are not valid Rust token streams, so they will cause a compiler error before the ts_string proc macro can parse them.
To solve this problem, thie macros in this crate allow us to insert string literals directly into the output.
So for instance we can escape the examples above like so:
let ts: String = ts_string! { const text = #"'some text here'"; }
println!("{}", ts);
let ts: String = ts_string! { const text = #"`some other text here`:"; }
println!("{}", ts);
This will print:
const text = 'some text here';
const text = `some other text here`;
Substitutions are also supported inside literal strings, and raw strings can be literal strings:
let t = "text"
let here = "here
let ts: String = ts_string! { const text = r##"'some #t #{here}'"##; }
println!("{}", ts); // prints: const text = 'some text here';
For interoperability with Deno, this library also provides the to_quote!
macro. This allows for creation of a deno_ast::ParsedSource
object:
let ts: Result<ParsedSource, deno_ast::Diagnostic> = ts_quote! { const foo = truel; };
This crate also provides the TSSource
convenience trait, which is implemented for ParsedSource
(aliased as TS
).
This trait provides a method for formatting:
let ts: ParsedSource = ts_quote! { const foo = truel; };
let source: anyhow::Result<Option<String>> = ts.formatted(None);
This method optionally takes a dprint_plugin_typescript::configuration::Configuration
to control the output configuration.
If None is provided, a common sense default will be used for formatting.
Here's an example using a custom config:
let ts: ParsedSource = ts_quote! { const foo = truel; };
let config = ConfigurationBuilder::new()
.indent_width(4)
.line_width(80)
.prefer_hanging(true)
.prefer_single_line(false)
.quote_style(QuoteStyle::PreferDouble)
.next_control_flow_position(NextControlFlowPosition::SameLine)
.build();
let source: anyhow::Result<String> = ts.formatted(Some(config));
The above example desugars to the following:
let ts: ParsedSource = ParsedSource::from_source( "const foo = truel;".to_string() );
let config = ConfigurationBuilder::new()
.indent_width(4)
.line_width(80)
.prefer_hanging(true)
.prefer_single_line(false)
.quote_style(QuoteStyle::PreferDouble)
.next_control_flow_position(NextControlFlowPosition::SameLine)
.build();
let source: anyhow::Result<String> = ts.formatted(Some(config));