diff --git a/CHANGELOG.md b/CHANGELOG.md index 0725c3b..60f15bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +- upgrade to latest full-moon ([#10](https://github.com/seaofvoices/darklua/pull/10)) - add a `pkg` alias entry to the generated `.luaurc` file in `node_modules` ([#9](https://github.com/seaofvoices/darklua/pull/9)) ## 0.1.1 diff --git a/README.md b/README.md index 6f1ae50..241e7ca 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,15 @@ +[![checks](https://github.com/seaofvoices/npmluau/actions/workflows/test.yml/badge.svg)](https://github.com/seaofvoices/npmluau/actions/workflows/test.yml) +![version](https://img.shields.io/github/package-json/v/seaofvoices/npmluau) +[![GitHub top language](https://img.shields.io/github/languages/top/seaofvoices/npmluau)](https://github.com/luau-lang/luau) +![license](https://img.shields.io/npm/l/npmluau) +![npm](https://img.shields.io/npm/dt/npmluau) + # npmluau This utility can be used to allow Luau projects to use npm as a package manager. It lets your projects use string requires: use relative file paths for the project's files or prefix your dependency names with `@pkg` to use them. +If you are interested to know why should use npm for Luau development, read [Why You Should Use npm for Luau](https://medium.com/@jeparlefrancais/why-you-should-use-npm-for-luau-22113f54f1fa). + If you are developing on a platform that does not support requires with, you can use a tool like [darklua](https://github.com/seaofvoices/darklua) to automatically convert requires into your platform specific implementation. ## How to use @@ -32,23 +40,16 @@ This utility will generate a folder named `.luau-aliases` inside `node_modules` **[Luau-lsp](https://github.com/JohnnyMorganz/luau-lsp)**: -If you using the VS code extension, you can define a directory alias in your workspace settings: +If you using the VS code extension, you can define a directory alias in your `.luaurc`: ```json { - "luau-lsp.require.directoryAliases": { - "@pkg": "node_modules/.luau-aliases" + "aliases": { + "pkg": "node_modules/.luau-aliases" } } ``` -If you are also running `luau-lsp` from the command line interface, you can provide the directory aliases within a configuration file and pass it to the `--settings` argument: +## License -```json -{ - "luau-lsp.require.mode": "relativeToFile", - "luau-lsp.require.directoryAliases": { - "@pkg": "node_modules/.luau-aliases" - } -} -``` +This project is available under the MIT license. See [LICENSE.txt](LICENSE.txt) for details. diff --git a/luau-types-re-export/Cargo.toml b/luau-types-re-export/Cargo.toml index 2c209c9..af21ec0 100644 --- a/luau-types-re-export/Cargo.toml +++ b/luau-types-re-export/Cargo.toml @@ -16,12 +16,12 @@ github = { repository = "seaofvoices/npmluau" } crate-type = ["cdylib", "rlib"] [dependencies] -full_moon = { version = "0.18.1", features = ["roblox"] } -stylua = { version = "0.18.2", features = ["luau"], default-features = false } +full_moon = { version = "1.2.0", features = ["roblox"] } +stylua = { version = "2.0.2", features = ["luau"], default-features = false } wasm-bindgen = "0.2" [dev-dependencies] -insta = "1.33.0" +insta = "1.42.0" [profile.release] lto = true diff --git a/luau-types-re-export/src/lib.rs b/luau-types-re-export/src/lib.rs index 09acfe6..b9e5830 100644 --- a/luau-types-re-export/src/lib.rs +++ b/luau-types-re-export/src/lib.rs @@ -2,10 +2,10 @@ use std::iter; use full_moon::{ ast::{ + luau::{ExportedTypeDeclaration, GenericParameterInfo, IndexedTypeInfo, TypeInfo}, punctuated::{Pair, Punctuated}, - types::{ExportedTypeDeclaration, GenericParameterInfo, IndexedTypeInfo, TypeInfo}, Block, Call, Expression, FunctionCall, LastStmt, LocalAssignment, Prefix, Return, Stmt, - Suffix, Value, Var, + Suffix, Var, }, tokenizer::{Symbol, Token, TokenReference, TokenType}, visitors::Visitor, @@ -35,7 +35,7 @@ fn create_string(content: &str) -> TokenReference { Vec::new(), Token::new(TokenType::StringLiteral { literal: ShortString::new(content), - multi_line: None, + multi_line_depth: 0, quote_type: full_moon::tokenizer::StringLiteralQuoteType::Double, }), Vec::new(), @@ -81,10 +81,10 @@ impl Visitor for CollectTypeExports { let generic_value = match pair.value().parameter() { GenericParameterInfo::Name(name) => TypeInfo::Basic(name.clone()), - GenericParameterInfo::Variadic { name, ellipse } => { + GenericParameterInfo::Variadic { name, ellipsis } => { TypeInfo::GenericPack { name: name.clone(), - ellipse: ellipse.clone(), + ellipsis: ellipsis.clone(), } } _ => unimplemented!("unknown GenericParameterInfo variant"), @@ -129,28 +129,35 @@ impl Visitor for CollectTypeExports { #[wasm_bindgen] pub fn reexport(module_path: &str, code: &str) -> Result { - let parsed_code = - full_moon::parse(code).map_err(|err| format!("unable to parse code: {}", err))?; + let parsed_code = full_moon::parse(code).map_err(|errors| match errors.len() { + 0 => "failed to parse code".to_owned(), + 1 => { + format!( + "unable to parse code: {}", + errors.first().expect("expected one error") + ) + } + _ => { + let display_errors: Vec<_> = errors.into_iter().map(|err| err.to_string()).collect(); + format!("unable to parse code:\n- {}", display_errors.join("\n- ")) + } + })?; let identifier = create_identifier("module"); let require_token = create_identifier("require"); let module_path_token = create_string(module_path); let module_definition = LocalAssignment::new(into_punctuated(identifier.clone())) - .with_expressions(into_punctuated(Expression::Value { - value: Box::new(Value::FunctionCall( - FunctionCall::new(Prefix::Name(require_token)).with_suffixes(vec![Suffix::Call( - Call::AnonymousCall(full_moon::ast::FunctionArgs::String(module_path_token)), - )]), - )), - type_assertion: None, - })) + .with_expressions(into_punctuated(Expression::FunctionCall( + FunctionCall::new(Prefix::Name(require_token)).with_suffixes(vec![Suffix::Call( + Call::AnonymousCall(full_moon::ast::FunctionArgs::String(module_path_token)), + )]), + ))) .with_equal_token(Some(create_symbol(Symbol::Equal))); - let return_module = Return::new().with_returns(into_punctuated(Expression::Value { - value: Box::new(Value::Var(Var::Name(identifier.clone()))), - type_assertion: None, - })); + let return_module = Return::new().with_returns(into_punctuated(Expression::Var(Var::Name( + identifier.clone(), + )))); let mut collect_exports = CollectTypeExports::new(identifier); @@ -169,15 +176,20 @@ pub fn reexport(module_path: &str, code: &str) -> Result { let formatted_ast = stylua_lib::format_ast( new_ast, - Config::new() - .with_quote_style(stylua_lib::QuoteStyle::AutoPreferSingle) - .with_column_width(80), + get_stylua_config(), None, stylua_lib::OutputVerification::None, ) .map_err(|err| format!("unable to format code: {}", err))?; - Ok(full_moon::print(&formatted_ast)) + Ok(formatted_ast.to_string()) +} + +fn get_stylua_config() -> Config { + let mut config = Config::new(); + config.quote_style = stylua_lib::QuoteStyle::AutoPreferSingle; + config.column_width = 80; + config } #[cfg(test)]