diff --git a/.editorconfig b/.editorconfig index 642b6cfd..6d461377 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,11 +1,168 @@ -# Top-most EditorConfig file root = true +# Top-most EditorConfig file [*] indent_style = space end_of_line = crlf indent_size = 4 +# Microsoft .NET properties +csharp_new_line_before_members_in_object_initializers = false +csharp_preferred_modifier_order = public, private, protected, internal, file, new, static, abstract, virtual, sealed, readonly, override, extern, unsafe, volatile, async, required:suggestion +csharp_space_between_method_call_parameter_list_parentheses = true +csharp_space_between_method_declaration_parameter_list_parentheses = true +csharp_space_between_parentheses = control_flow_statements,expressions +csharp_style_prefer_utf8_string_literals = true:suggestion +csharp_style_var_elsewhere = false:silent +csharp_style_var_for_built_in_types = false:silent +csharp_style_var_when_type_is_apparent = false:silent +dotnet_naming_rule.constants_rule.import_to_resharper = as_predefined +dotnet_naming_rule.constants_rule.severity = warning +dotnet_naming_rule.constants_rule.style = lower_camel_case_style +dotnet_naming_rule.constants_rule.symbols = constants_symbols +dotnet_naming_rule.private_constants_rule.import_to_resharper = as_predefined +dotnet_naming_rule.private_constants_rule.severity = warning +dotnet_naming_rule.private_constants_rule.style = upper_camel_case_style +dotnet_naming_rule.private_constants_rule.symbols = private_constants_symbols +dotnet_naming_rule.private_static_readonly_rule.import_to_resharper = as_predefined +dotnet_naming_rule.private_static_readonly_rule.severity = warning +dotnet_naming_rule.private_static_readonly_rule.style = lower_camel_case_style_1 +dotnet_naming_rule.private_static_readonly_rule.symbols = private_static_readonly_symbols +dotnet_naming_style.lower_camel_case_style.capitalization = camel_case +dotnet_naming_style.lower_camel_case_style_1.capitalization = camel_case +dotnet_naming_style.lower_camel_case_style_1.required_prefix = _ +dotnet_naming_style.upper_camel_case_style.capitalization = pascal_case +dotnet_naming_symbols.constants_symbols.applicable_accessibilities = public,internal,protected,protected_internal,private_protected +dotnet_naming_symbols.constants_symbols.applicable_kinds = field +dotnet_naming_symbols.constants_symbols.required_modifiers = const +dotnet_naming_symbols.private_constants_symbols.applicable_accessibilities = private +dotnet_naming_symbols.private_constants_symbols.applicable_kinds = field +dotnet_naming_symbols.private_constants_symbols.required_modifiers = const +dotnet_naming_symbols.private_static_readonly_symbols.applicable_accessibilities = private +dotnet_naming_symbols.private_static_readonly_symbols.applicable_kinds = field +dotnet_naming_symbols.private_static_readonly_symbols.required_modifiers = static,readonly +dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:none +dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none +dotnet_style_predefined_type_for_locals_parameters_members = true:error +dotnet_style_predefined_type_for_member_access = true:silent +dotnet_style_qualification_for_event = false:silent +dotnet_style_qualification_for_field = false:silent +dotnet_style_qualification_for_method = false:silent +dotnet_style_qualification_for_property = false:silent +dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent + +# ReSharper properties +resharper_csharp_keep_blank_lines_in_code = 1 +resharper_csharp_keep_blank_lines_in_declarations = 1 +resharper_csharp_max_line_length = 0 +resharper_csharp_wrap_lines = false +resharper_enforce_line_ending_style = true +resharper_keep_existing_attribute_arrangement = true +resharper_max_attribute_length_for_same_line = 0 +resharper_place_accessorholder_attribute_on_same_line = false +resharper_place_accessor_attribute_on_same_line = false +resharper_place_field_attribute_on_same_line = false +resharper_show_autodetect_configure_formatting_tip = false +resharper_space_within_array_access_brackets = true +resharper_space_within_checked_parentheses = true +resharper_space_within_default_parentheses = true +resharper_space_within_nameof_parentheses = true +resharper_space_within_sizeof_parentheses = true +resharper_space_within_typeof_parentheses = true +resharper_use_indent_from_vs = false +resharper_xml_keep_user_linebreaks = false +resharper_xml_wrap_lines = false +resharper_xml_wrap_tags_and_pi = false + +# ReSharper inspection severities +resharper_arguments_style_other_highlighting = error +resharper_arrange_object_creation_when_type_not_evident_highlighting = none +resharper_arrange_redundant_parentheses_highlighting = error +resharper_arrange_static_member_qualifier_highlighting = error +resharper_arrange_this_qualifier_highlighting = error +resharper_comment_typo_highlighting = warning +resharper_compare_of_floats_by_equality_operator_highlighting = none +resharper_convert_if_statement_to_return_statement_highlighting = none +resharper_convert_to_constant_local_highlighting = warning +resharper_html_id_not_resolved_highlighting = none +resharper_html_path_error_highlighting = none +resharper_inline_out_variable_declaration_highlighting = none +resharper_localizable_element_highlighting = none +resharper_member_can_be_private_global_highlighting = none +resharper_not_accessed_field_local_highlighting = none +resharper_parameter_type_can_be_enumerable_local_highlighting = warning +resharper_razor_section_not_resolved_highlighting = none +resharper_redundant_argument_default_value_highlighting = none +resharper_redundant_empty_object_creation_argument_list_highlighting = error +resharper_redundant_using_directive_highlighting = error +resharper_replace_substring_with_range_indexer_highlighting = warning +resharper_switch_statement_handles_some_known_enum_values_with_default_highlighting = none +resharper_use_nameof_expression_highlighting = error +csharp_indent_labels = one_less_than_current +csharp_using_directive_placement = outside_namespace:silent +csharp_prefer_simple_using_statement = true:silent +csharp_prefer_braces = true:silent +csharp_style_namespace_declarations = block_scoped:silent +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:silent +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent +csharp_space_around_binary_operators = before_and_after +csharp_style_throw_expression = true:silent +csharp_style_prefer_null_check_over_type_check = true:silent +csharp_style_prefer_index_operator = true:silent +csharp_style_prefer_local_over_anonymous_function = true:silent +csharp_prefer_simple_default_expression = true:silent +csharp_style_prefer_tuple_swap = true:silent +csharp_style_implicit_object_creation_when_type_is_apparent = true:silent +csharp_style_prefer_range_operator = true:silent +csharp_style_inlined_variable_declaration = true:silent +csharp_style_unused_value_assignment_preference = discard_variable:silent +csharp_style_deconstructed_variable_declaration = true:silent +csharp_style_unused_value_expression_statement_preference = discard_variable:silent +csharp_prefer_static_local_function = true:silent +csharp_style_prefer_readonly_struct = true:suggestion +csharp_style_prefer_readonly_struct_member = true:suggestion +csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent +csharp_style_conditional_delegate_call = true:silent +dotnet_diagnostic.RS0035.severity = silent + [*.json] indent_style = space -indent_size = 2 \ No newline at end of file +indent_size = 2 + +[*.{appxmanifest,asax,ascx,aspx,axaml,axml,build,config,cs,cshtml,csproj,dbml,discomap,dtd,htm,html,jsproj,lsproj,master,njsproj,nuspec,paml,proj,props,razor,resw,resx,skin,StyleCop,targets,tasks,vb,vbproj,xaml,xamlx,xml,xoml,xsd}] +indent_style = space +indent_size = 4 +tab_width = 4 +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_coalesce_expression = true:silent +dotnet_style_null_propagation = true:silent +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_object_initializer = true:silent +dotnet_style_collection_initializer = true:silent +dotnet_style_prefer_simplified_boolean_expressions = true:silent +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_explicit_tuple_names = true:silent +dotnet_style_prefer_inferred_tuple_names = true:silent +dotnet_style_prefer_inferred_anonymous_type_member_names = true:silent +dotnet_style_prefer_compound_assignment = true:silent +dotnet_style_prefer_simplified_interpolation = true:suggestion +dotnet_style_namespace_match_folder = true:silent +dotnet_style_readonly_field = true:silent +dotnet_style_allow_multiple_blank_lines_experimental = true:silent +dotnet_style_allow_statement_immediately_after_block_experimental = true:silent +dotnet_code_quality_unused_parameters = all:silent diff --git a/.gitignore b/.gitignore index 80692d44..88ff2ea5 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ _NCrunch_WebCompiler#Node src/WebCompiler/Node/node_modules/* /src/WebCompiler/Node/node.exe /src/WebCompiler/Node/package-lock.json +/src/WebCompiler/Node/package.json diff --git a/WebCompiler.sln b/WebCompiler.sln index c3380f98..64b5711b 100644 --- a/WebCompiler.sln +++ b/WebCompiler.sln @@ -1,22 +1,26 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33801.468 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebCompilerVsix", "src\WebCompilerVsix\WebCompilerVsix.csproj", "{49C270BE-9645-40D5-BE08-91ADE243D394}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebCompiler", "src\WebCompiler\WebCompiler.csproj", "{B714B5B9-27C4-443C-9517-FE5C5EF46EA2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebCompiler", "src\WebCompiler\WebCompiler.csproj", "{B714B5B9-27C4-443C-9517-FE5C5EF46EA2}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebCompilerTest", "src\WebCompilerTest\WebCompilerTest.csproj", "{43AAA3AD-A806-45A0-99A3-F0E7E3B81AEB}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E9E392DE-6C44-4AD2-858C-D73AD3016E6E}" ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig appveyor.yml = appveyor.yml build\build.cmd = build\build.cmd CHANGELOG.md = CHANGELOG.md README.md = README.md + build\build.sh = build\build.sh EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebCompilerTestsCore", "src\WebCompilerTestsCore\WebCompilerTestsCore.csproj", "{F6D33ECE-F6A1-4F60-977E-42C70708921D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -35,6 +39,10 @@ Global {43AAA3AD-A806-45A0-99A3-F0E7E3B81AEB}.Debug|Any CPU.Build.0 = Debug|Any CPU {43AAA3AD-A806-45A0-99A3-F0E7E3B81AEB}.Release|Any CPU.ActiveCfg = Release|Any CPU {43AAA3AD-A806-45A0-99A3-F0E7E3B81AEB}.Release|Any CPU.Build.0 = Release|Any CPU + {F6D33ECE-F6A1-4F60-977E-42C70708921D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F6D33ECE-F6A1-4F60-977E-42C70708921D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F6D33ECE-F6A1-4F60-977E-42C70708921D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F6D33ECE-F6A1-4F60-977E-42C70708921D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/build/build.sh b/build/build.sh new file mode 100644 index 00000000..699e0793 --- /dev/null +++ b/build/build.sh @@ -0,0 +1,81 @@ +#!/bin/bash + +#:: IMPORTANT!! npm 3.x is required to avoid long path exceptions + +#// TODO: GH: replace this with linux version +#if exist "../src/WebCompiler/node/node_modules.7z" goto:EOF + +mkdir ../src/WebCompiler/node + +pushd ../src/WebCompiler/node + +# node-sass \ // TODO: GH: is this really needed? it fails to install on OS X +echo Installing packages... +npm install --quiet \ + babel@5.8.34 \ + iced-coffee-script \ + less \ + less-plugin-autoprefix \ + less-plugin-csscomb \ + sass \ + postcss@latest \ + postcss-cli \ + autoprefixer \ + stylus \ + handlebars \ + > /dev/null +npm install --quiet > /dev/null + +#if not exist "node_modules/node-sass/vendor/win32-ia32-48" ( +# echo Copying node binding... +# md "node_modules/node-sass/vendor/win32-ia32-48" +# copy binding.node "node_modules/node-sass/vendor/win32-ia32-48" +#) + +echo Deleting unneeded files and folders... +rm -rf *.html > /dev/null +rm -rf *.markdown > /dev/null +rm -rf *.md > /dev/null +rm -rf *.npmignore > /dev/null +rm -rf *.patch > /dev/null +rm -rf *.txt > /dev/null +rm -rf *.yml > /dev/null +rm -rf .editorconfig > /dev/null +rm -rf .eslintrc > /dev/null +rm -rf .gitattributes > /dev/null +rm -rf .jscsrc > /dev/null +rm -rf .jshintrc > /dev/null +rm -rf CHANGELOG > /dev/null +rm -rf CNAME > /dev/null +rm -rf example.js > /dev/null +rm -rf generate-* > /dev/null +rm -rf gruntfile.js > /dev/null +rm -rf gulpfile.* > /dev/null +rm -rf makefile.* > /dev/null +rm -rf README > /dev/null + +# TODO: limux version of the below +#for /d /r . %%d in (benchmark) do @if exist "%%d" rd /s /q "%%d" > /dev/null +#for /d /r . %%d in (bench) do @if exist "%%d" rd /s /q "%%d" > /dev/null +#for /d /r . %%d in (doc) do @if exist "%%d" rd /s /q "%%d" > /dev/null +#for /d /r . %%d in (docs) do @if exist "%%d" rd /s /q "%%d" > /dev/null +#for /d /r . %%d in (example) do @if exist "%%d" rd /s /q "%%d" > /dev/null +#for /d /r . %%d in (examples) do @if exist "%%d" rd /s /q "%%d" > /dev/null +#for /d /r . %%d in (images) do @if exist "%%d" rd /s /q "%%d" > /dev/null +#for /d /r . %%d in (man) do @if exist "%%d" rd /s /q "%%d" > /dev/null +#for /d /r . %%d in (media) do @if exist "%%d" rd /s /q "%%d" > /dev/null +#for /d /r . %%d in (scripts) do @if exist "%%d" rd /s /q "%%d" > /dev/null +#for /d /r . %%d in (test) do @if exist "%%d" rd /s /q "%%d" > /dev/null +#for /d /r . %%d in (tests) do @if exist "%%d" rd /s /q "%%d" > /dev/null +#for /d /r . %%d in (testing) do @if exist "%%d" rd /s /q "%%d" > /dev/null +#for /d /r . %%d in (tst) do @if exist "%%d" rd /s /q "%%d" > /dev/null + +echo Compressing artifacts and cleans up... +rm node_modules.7z +7z a -r -mx9 node_modules.7z node_modules > /dev/null +rm -rf node_modules > /dev/null +rm package.json > /dev/null + +#:done +echo Done +popd \ No newline at end of file diff --git a/src/WebCompiler/Compile/BabelCompiler.cs b/src/WebCompiler/Compile/BabelCompiler.cs index 90f8b890..6d93b512 100644 --- a/src/WebCompiler/Compile/BabelCompiler.cs +++ b/src/WebCompiler/Compile/BabelCompiler.cs @@ -79,21 +79,47 @@ private void RunCompilerProcess(Config config, FileInfo info) { string arguments = ConstructArguments(config); + string processFileName; + string processArguments; + switch ( Environment.OSVersion.Platform ) + { + case PlatformID.Unix: + case PlatformID.MacOSX: + processFileName = Path.Combine(_path, "node_modules/.bin/babel"); + processArguments = $"{arguments} \"{info.FullName}\""; + break; + + default: + processFileName = "cmd.exe"; + processArguments = $"/c \"\"{Path.Combine(_path, "node_modules\\.bin\\babel.cmd")}\" {arguments} \"{info.FullName}\" \""; + break; + } + ProcessStartInfo start = new ProcessStartInfo { WorkingDirectory = info.Directory.FullName, UseShellExecute = false, WindowStyle = ProcessWindowStyle.Hidden, CreateNoWindow = true, - FileName = "cmd.exe", - Arguments = $"/c \"\"{Path.Combine(_path, "node_modules\\.bin\\babel.cmd")}\" {arguments} \"{info.FullName}\"\"", + FileName = processFileName, + Arguments = processArguments, StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8, RedirectStandardOutput = true, RedirectStandardError = true, }; - start.EnvironmentVariables["PATH"] = _path + ";" + start.EnvironmentVariables["PATH"]; + switch ( Environment.OSVersion.Platform ) + { + case PlatformID.Unix: + case PlatformID.MacOSX: + start.EnvironmentVariables["PATH"] = _path + ":" + start.EnvironmentVariables["PATH"]; + break; + + default: + start.EnvironmentVariables["PATH"] = _path + ";" + start.EnvironmentVariables["PATH"]; + break; + } using (Process p = Process.Start(start)) { diff --git a/src/WebCompiler/Compile/CompilerService.cs b/src/WebCompiler/Compile/CompilerService.cs index 9b760f9b..5d504846 100644 --- a/src/WebCompiler/Compile/CompilerService.cs +++ b/src/WebCompiler/Compile/CompilerService.cs @@ -78,7 +78,20 @@ internal static ICompiler GetCompiler(Config config) public static void Initialize() { var node_modules = Path.Combine(_path, "node_modules"); - var node_exe = Path.Combine(_path, "node.exe"); + + string node_exe; + switch ( Environment.OSVersion.Platform ) + { + case PlatformID.Unix: + case PlatformID.MacOSX: + node_exe = "node"; + break; + + default: + node_exe = "node.exe"; + break; + } + var log_file = Path.Combine(_path, "log.txt"); lock (_syncRoot) @@ -93,17 +106,35 @@ public static void Initialize() Directory.CreateDirectory(_path); SaveResourceFile(_path, "WebCompiler.Node.node.7z", "node.7z"); SaveResourceFile(_path, "WebCompiler.Node.node_modules.7z", "node_modules.7z"); - SaveResourceFile(_path, "WebCompiler.Node.7z.exe", "7z.exe"); - SaveResourceFile(_path, "WebCompiler.Node.7z.dll", "7z.dll"); - SaveResourceFile(_path, "WebCompiler.Node.prepare.cmd", "prepare.cmd"); + + string processFileName; + string processArguments; + switch ( System.Environment.OSVersion.Platform ) + { + case PlatformID.Unix: + case PlatformID.MacOSX: + SaveResourceFile(_path, "WebCompiler.Node.prepare.sh", "prepare.sh"); + processFileName = "/bin/bash"; + processArguments = "prepare.sh"; + break; + + default: + SaveResourceFile(_path, "WebCompiler.Node.7z.exe", "7z.exe"); + SaveResourceFile(_path, "WebCompiler.Node.7z.dll", "7z.dll"); + SaveResourceFile(_path, "WebCompiler.Node.prepare.cmd", "prepare.cmd"); + processFileName = "cmd.exe"; + processArguments = "/c prepare.cmd"; + break; + } + ProcessStartInfo start = new ProcessStartInfo { WorkingDirectory = _path, CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden, - FileName = "cmd.exe", - Arguments = "/c prepare.cmd" + FileName = processFileName, + Arguments = processArguments }; Process p = Process.Start(start); diff --git a/src/WebCompiler/Compile/HandlebarsCompiler.cs b/src/WebCompiler/Compile/HandlebarsCompiler.cs index 7a0070ef..2a225ef6 100644 --- a/src/WebCompiler/Compile/HandlebarsCompiler.cs +++ b/src/WebCompiler/Compile/HandlebarsCompiler.cs @@ -25,7 +25,7 @@ public HandlebarsCompiler(string path) public CompilerResult Compile(Config config) { string baseFolder = Path.GetDirectoryName(config.FileName); - string inputFile = Path.Combine(baseFolder, config.InputFile); + string inputFile = Path.GetFullPath( Path.Combine(baseFolder, config.InputFile) ); FileInfo info = new FileInfo(inputFile); string content = File.ReadAllText(info.FullName); @@ -125,21 +125,47 @@ private void RunCompilerProcess(Config config, FileInfo info) { string arguments = ConstructArguments(config); + string processFileName; + string processArguments; + switch ( Environment.OSVersion.Platform ) + { + case PlatformID.Unix: + case PlatformID.MacOSX: + processFileName = Path.Combine(_path, "node_modules/.bin/handlebars"); + processArguments = $"{arguments} \"{info.FullName}\""; + break; + + default: + processFileName = "cmd.exe"; + processArguments = $"/c \"\"{Path.Combine(_path, "node_modules\\.bin\\handlebars.cmd")}\" {arguments} \"{info.FullName}\" \""; + break; + } + ProcessStartInfo start = new ProcessStartInfo { WorkingDirectory = info.Directory.FullName, UseShellExecute = false, WindowStyle = ProcessWindowStyle.Hidden, CreateNoWindow = true, - FileName = "cmd.exe", - Arguments = $"/c \"\"{Path.Combine(_path, "node_modules\\.bin\\handlebars.cmd")}\" \"{info.FullName}\" {arguments}\"", + FileName = processFileName, + Arguments = processArguments, StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8, RedirectStandardOutput = true, RedirectStandardError = true, }; - start.EnvironmentVariables["PATH"] = _path + ";" + start.EnvironmentVariables["PATH"]; + switch ( Environment.OSVersion.Platform ) + { + case PlatformID.Unix: + case PlatformID.MacOSX: + start.EnvironmentVariables["PATH"] = _path + ":" + start.EnvironmentVariables["PATH"]; + break; + + default: + start.EnvironmentVariables["PATH"] = _path + ";" + start.EnvironmentVariables["PATH"]; + break; + } using (Process p = Process.Start(start)) { diff --git a/src/WebCompiler/Compile/IcedCoffeeScriptCompiler.cs b/src/WebCompiler/Compile/IcedCoffeeScriptCompiler.cs index 65b1aecb..a5605e9e 100644 --- a/src/WebCompiler/Compile/IcedCoffeeScriptCompiler.cs +++ b/src/WebCompiler/Compile/IcedCoffeeScriptCompiler.cs @@ -97,19 +97,45 @@ private void RunCompilerProcess(Config config, FileInfo info) { string arguments = ConstructArguments(config); + string processFileName; + string processArguments; + switch ( Environment.OSVersion.Platform ) + { + case PlatformID.Unix: + case PlatformID.MacOSX: + processFileName = Path.Combine(_path, "node_modules/.bin/iced"); + processArguments = $"{arguments} \"{info.FullName}\""; + break; + + default: + processFileName = "cmd.exe"; + processArguments = $"/c \"\"{Path.Combine(_path, "node_modules\\.bin\\iced.cmd")}\" {arguments} \"{info.FullName}\" \""; + break; + } + ProcessStartInfo start = new ProcessStartInfo { WorkingDirectory = info.Directory.FullName, UseShellExecute = false, WindowStyle = ProcessWindowStyle.Hidden, CreateNoWindow = true, - FileName = "cmd.exe", - Arguments = $"/c \"\"{Path.Combine(_path, "node_modules\\.bin\\iced.cmd")}\" {arguments} \"{info.FullName}\"\"", + FileName = processFileName, + Arguments = processArguments, StandardErrorEncoding = Encoding.UTF8, RedirectStandardError = true, }; - start.EnvironmentVariables["PATH"] = _path + ";" + start.EnvironmentVariables["PATH"]; + switch ( Environment.OSVersion.Platform ) + { + case PlatformID.Unix: + case PlatformID.MacOSX: + start.EnvironmentVariables["PATH"] = _path + ":" + start.EnvironmentVariables["PATH"]; + break; + + default: + start.EnvironmentVariables["PATH"] = _path + ";" + start.EnvironmentVariables["PATH"]; + break; + } using (Process p = Process.Start(start)) { diff --git a/src/WebCompiler/Compile/LessCompiler.cs b/src/WebCompiler/Compile/LessCompiler.cs index e0c63405..ef8d8994 100644 --- a/src/WebCompiler/Compile/LessCompiler.cs +++ b/src/WebCompiler/Compile/LessCompiler.cs @@ -79,21 +79,47 @@ private void RunCompilerProcess(Config config, FileInfo info) { string arguments = ConstructArguments(config); + string processFileName; + string processArguments; + switch ( Environment.OSVersion.Platform ) + { + case PlatformID.Unix: + case PlatformID.MacOSX: + processFileName = Path.Combine(_path, "node_modules/.bin/lessc"); + processArguments = $"{arguments} \"{info.FullName}\""; + break; + + default: + processFileName = "cmd.exe"; + processArguments = $"/c \"\"{Path.Combine(_path, "node_modules\\.bin\\lessc.cmd")}\" {arguments} \"{info.FullName}\" \""; + break; + } + ProcessStartInfo start = new ProcessStartInfo { WorkingDirectory = info.Directory.FullName, UseShellExecute = false, WindowStyle = ProcessWindowStyle.Hidden, CreateNoWindow = true, - FileName = "cmd.exe", - Arguments = $"/c \"\"{Path.Combine(_path, "node_modules\\.bin\\lessc.cmd")}\" {arguments} \"{info.FullName}\"\"", + FileName = processFileName, + Arguments = processArguments, StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8, RedirectStandardOutput = true, RedirectStandardError = true, }; - start.EnvironmentVariables["PATH"] = _path + ";" + start.EnvironmentVariables["PATH"]; + switch ( Environment.OSVersion.Platform ) + { + case PlatformID.Unix: + case PlatformID.MacOSX: + start.EnvironmentVariables["PATH"] = _path + ":" + start.EnvironmentVariables["PATH"]; + break; + + default: + start.EnvironmentVariables["PATH"] = _path + ";" + start.EnvironmentVariables["PATH"]; + break; + } using (Process p = Process.Start(start)) { diff --git a/src/WebCompiler/Compile/NodeSassCompiler.cs b/src/WebCompiler/Compile/NodeSassCompiler.cs index 5f0dab16..a4af2bab 100644 --- a/src/WebCompiler/Compile/NodeSassCompiler.cs +++ b/src/WebCompiler/Compile/NodeSassCompiler.cs @@ -81,14 +81,30 @@ private void RunCompilerProcess(Config config, FileInfo info) { string arguments = ConstructArguments(config); + string processFileName; + string processArguments; + switch ( Environment.OSVersion.Platform ) + { + case PlatformID.Unix: + case PlatformID.MacOSX: + processFileName = Path.Combine(_path, "node_modules/.bin/node-sass"); + processArguments = $"{arguments} \"{info.FullName}\""; + break; + + default: + processFileName = "cmd.exe"; + processArguments = $"/c \"\"{Path.Combine(_path, "node_modules\\.bin\\node-sass.cmd")}\" {arguments} \"{info.FullName}\" \""; + break; + } + ProcessStartInfo start = new ProcessStartInfo { WorkingDirectory = new FileInfo(config.FileName).DirectoryName, // use config's directory to fix source map relative paths UseShellExecute = false, WindowStyle = ProcessWindowStyle.Hidden, CreateNoWindow = true, - FileName = "cmd.exe", - Arguments = $"/c \"\"{Path.Combine(_path, "node_modules\\.bin\\node-sass.cmd")}\" {arguments} \"{info.FullName}\" \"", + FileName = processFileName, + Arguments = processArguments, StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8, RedirectStandardOutput = true, @@ -104,11 +120,33 @@ private void RunCompilerProcess(Config config, FileInfo info) if (!options.SourceMap && !config.SourceMap) postCssArguments += " --no-map"; - start.Arguments = start.Arguments.TrimEnd('"') + $" | \"{Path.Combine(_path, "node_modules\\.bin\\postcss.cmd")}\" {postCssArguments}\""; + switch ( Environment.OSVersion.Platform ) + { + case PlatformID.Unix: + case PlatformID.MacOSX: + start.Arguments = start.Arguments + $" | \"{Path.Combine(_path, "node_modules/.bin/postcss")}\" {postCssArguments}\""; + break; + + default: + start.Arguments = start.Arguments.TrimEnd('"') + $" | \"{Path.Combine(_path, "node_modules\\.bin\\postcss.cmd")}\" {postCssArguments}\""; + break; + } + + start.EnvironmentVariables.Add("BROWSERSLIST", options.AutoPrefix); } - start.EnvironmentVariables["PATH"] = _path + ";" + start.EnvironmentVariables["PATH"]; + switch ( Environment.OSVersion.Platform ) + { + case PlatformID.Unix: + case PlatformID.MacOSX: + start.EnvironmentVariables["PATH"] = _path + ":" + start.EnvironmentVariables["PATH"]; + break; + + default: + start.EnvironmentVariables["PATH"] = _path + ";" + start.EnvironmentVariables["PATH"]; + break; + } using (Process p = Process.Start(start)) { diff --git a/src/WebCompiler/Compile/SassCompiler.cs b/src/WebCompiler/Compile/SassCompiler.cs index ee2fa65f..7296495a 100644 --- a/src/WebCompiler/Compile/SassCompiler.cs +++ b/src/WebCompiler/Compile/SassCompiler.cs @@ -23,7 +23,7 @@ public SassCompiler(string path) public CompilerResult Compile(Config config) { string baseFolder = Path.GetDirectoryName(config.FileName); - string inputFile = Path.Combine(baseFolder, config.InputFile); + string inputFile = Path.GetFullPath( Path.Combine(baseFolder, config.InputFile) ); FileInfo info = new FileInfo(inputFile); string content = File.ReadAllText(info.FullName); @@ -82,14 +82,30 @@ private void RunCompilerProcess(Config config, FileInfo info) { string arguments = ConstructArguments(config); + string processFileName; + string processArguments; + switch ( Environment.OSVersion.Platform ) + { + case PlatformID.Unix: + case PlatformID.MacOSX: + processFileName = Path.Combine(_path, "node_modules/.bin/sass"); + processArguments = $"{arguments} \"{info.FullName}\""; + break; + + default: + processFileName = "cmd.exe"; + processArguments = $"/c \"\"{Path.Combine(_path, "node_modules\\.bin\\sass.cmd")}\" {arguments} \"{info.FullName}\" \""; + break; + } + ProcessStartInfo start = new ProcessStartInfo { WorkingDirectory = new FileInfo(config.FileName).DirectoryName, // use config's directory to fix source map relative paths UseShellExecute = false, WindowStyle = ProcessWindowStyle.Hidden, CreateNoWindow = true, - FileName = "cmd.exe", - Arguments = $"/c \"\"{Path.Combine(_path, "node_modules\\.bin\\sass.cmd")}\" {arguments} \"{info.FullName}\" \"", + FileName = processFileName, + Arguments = processArguments, StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8, RedirectStandardOutput = true, @@ -107,12 +123,33 @@ private void RunCompilerProcess(Config config, FileInfo info) postCssArguments += " --no-map"; } - start.Arguments = start.Arguments.TrimEnd('"') + $" | \"{Path.Combine(_path, "node_modules\\.bin\\postcss.cmd")}\" {postCssArguments}\""; + switch ( Environment.OSVersion.Platform ) + { + case PlatformID.Unix: + case PlatformID.MacOSX: + start.Arguments = $"-c \"\"{start.FileName}\" {start.Arguments}" + $" | \"{Path.Combine(_path, "node_modules/.bin/postcss")}\" {postCssArguments}\""; + start.FileName = "/bin/bash"; + break; + + default: + start.Arguments = start.Arguments.TrimEnd('"') + $" | \"{Path.Combine(_path, "node_modules\\.bin\\postcss.cmd")}\" {postCssArguments}\""; + break; + } start.EnvironmentVariables.Add("BROWSERSLIST", options.AutoPrefix); } - start.EnvironmentVariables["PATH"] = _path + ";" + start.EnvironmentVariables["PATH"]; - + switch ( Environment.OSVersion.Platform ) + { + case PlatformID.Unix: + case PlatformID.MacOSX: + start.EnvironmentVariables["PATH"] = _path + ":" + start.EnvironmentVariables["PATH"]; + break; + + default: + start.EnvironmentVariables["PATH"] = _path + ";" + start.EnvironmentVariables["PATH"]; + break; + } + using (Process p = Process.Start(start)) { var stdout = p.StandardOutput.ReadToEndAsync(); diff --git a/src/WebCompiler/Compile/StylusCompiler.cs b/src/WebCompiler/Compile/StylusCompiler.cs index cd3ccd07..037b9fe3 100644 --- a/src/WebCompiler/Compile/StylusCompiler.cs +++ b/src/WebCompiler/Compile/StylusCompiler.cs @@ -80,21 +80,47 @@ private void RunCompilerProcess(Config config, FileInfo info) { string arguments = ConstructArguments(config); + string processFileName; + string processArguments; + switch ( Environment.OSVersion.Platform ) + { + case PlatformID.Unix: + case PlatformID.MacOSX: + processFileName = Path.Combine(_path, "node_modules/.bin/stylus"); + processArguments = $"{arguments} \"{info.FullName}\""; + break; + + default: + processFileName = "cmd.exe"; + processArguments = $"/c \"\"{Path.Combine(_path, "node_modules\\.bin\\stylus.cmd")}\" {arguments} \"{info.FullName}\" \""; + break; + } + ProcessStartInfo start = new ProcessStartInfo { WorkingDirectory = info.Directory.FullName, UseShellExecute = false, WindowStyle = ProcessWindowStyle.Hidden, CreateNoWindow = true, - FileName = "cmd.exe", - Arguments = $"/c \"\"{Path.Combine(_path, "node_modules\\.bin\\stylus.cmd")}\" {arguments} \"{info.FullName}\"\"", + FileName = processFileName, + Arguments = processArguments, StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8, RedirectStandardOutput = true, RedirectStandardError = true, }; - start.EnvironmentVariables["PATH"] = _path + ";" + start.EnvironmentVariables["PATH"]; + switch ( Environment.OSVersion.Platform ) + { + case PlatformID.Unix: + case PlatformID.MacOSX: + start.EnvironmentVariables["PATH"] = _path + ":" + start.EnvironmentVariables["PATH"]; + break; + + default: + start.EnvironmentVariables["PATH"] = _path + ";" + start.EnvironmentVariables["PATH"]; + break; + } using (Process p = Process.Start(start)) { diff --git a/src/WebCompiler/Config/Config.cs b/src/WebCompiler/Config/Config.cs index 95aecee6..45c68fcf 100644 --- a/src/WebCompiler/Config/Config.cs +++ b/src/WebCompiler/Config/Config.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Linq; @@ -68,7 +69,7 @@ public class Config public FileInfo GetAbsoluteInputFile() { string folder = new FileInfo(FileName).DirectoryName; - return new FileInfo(Path.Combine(folder, InputFile.Replace("/", "\\"))); + return new FileInfo(Path.Combine(folder, InputFile.Replace('/', Path.DirectorySeparatorChar))); } /// @@ -77,7 +78,7 @@ public FileInfo GetAbsoluteInputFile() public FileInfo GetAbsoluteOutputFile() { string folder = new FileInfo(FileName).DirectoryName; - return new FileInfo(Path.Combine(folder, OutputFile.Replace("/", "\\"))); + return new FileInfo(Path.Combine(folder, OutputFile.Replace('/', Path.DirectorySeparatorChar))); } /// diff --git a/src/WebCompiler/Config/ConfigFileProcessor.cs b/src/WebCompiler/Config/ConfigFileProcessor.cs index aedc8dda..df305503 100644 --- a/src/WebCompiler/Config/ConfigFileProcessor.cs +++ b/src/WebCompiler/Config/ConfigFileProcessor.cs @@ -23,6 +23,8 @@ public class ConfigFileProcessor /// A list of compiler results. public IEnumerable Process(string configFile, IEnumerable configs = null, bool force = false) { + configFile = Path.GetFullPath(configFile); + if (_processing.Contains(configFile)) return Enumerable.Empty(); @@ -92,7 +94,7 @@ public IEnumerable SourceFileChanged(string configFile, string sourceFile, string projectPath) { - return SourceFileChanged(configFile, sourceFile, projectPath, new HashSet()); + return SourceFileChanged(Path.GetFullPath(configFile), sourceFile, projectPath, new HashSet()); } /// @@ -112,7 +114,7 @@ private IEnumerable SourceFileChanged(string configFile, // Compile if the file if it's referenced directly in compilerconfig.json foreach (Config config in configs) { - string input = Path.Combine(folder, config.InputFile.Replace("/", "\\")); + string input = Path.Combine(folder, config.InputFile.Replace('/', Path.DirectorySeparatorChar)); if (input.Equals(sourceFile, StringComparison.OrdinalIgnoreCase)) { @@ -171,7 +173,7 @@ public static IEnumerable IsFileConfigured(string configFile, string sou foreach (Config config in configs) { - string input = Path.Combine(folder, config.InputFile.Replace("/", "\\")); + string input = Path.Combine(folder, config.InputFile.Replace('/', Path.DirectorySeparatorChar)); if (input.Equals(sourceFile, StringComparison.OrdinalIgnoreCase)) list.Add(config); diff --git a/src/WebCompiler/Helpers/FileHelpers.cs b/src/WebCompiler/Helpers/FileHelpers.cs index f844736d..e9128144 100644 --- a/src/WebCompiler/Helpers/FileHelpers.cs +++ b/src/WebCompiler/Helpers/FileHelpers.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Linq; namespace WebCompiler { @@ -13,11 +14,46 @@ public static class FileHelpers /// public static string MakeRelative(string baseFile, string file) { - Uri baseUri = new Uri(baseFile, UriKind.RelativeOrAbsolute); - Uri fileUri = new Uri(file, UriKind.RelativeOrAbsolute); + //Uri baseUri = new Uri(baseFile, UriKind.RelativeOrAbsolute); + //Uri fileUri = new Uri(file, UriKind.RelativeOrAbsolute); - return Uri.UnescapeDataString(baseUri.MakeRelativeUri(fileUri).ToString()); - } + //return Uri.UnescapeDataString(baseUri.MakeRelativeUri(fileUri).ToString()); + + var basePath = Path.GetFullPath( baseFile ); + var filePath = Path.GetFullPath( file ); + + // remove the common ancestory of the two paths + var basePathParts = basePath.Split(Path.DirectorySeparatorChar).ToList(); + var filePathParts = filePath.Split(Path.DirectorySeparatorChar).ToList(); + while( basePathParts.Any() && filePathParts.Any() && basePathParts.FirstOrDefault() == filePathParts.FirstOrDefault() ) + { + basePathParts.RemoveAt(0); + filePathParts.RemoveAt(0); + } + + if ( basePathParts.Count == 0 && filePathParts.Count == 0) + { + return String.Join( Path.DirectorySeparatorChar, ".", Path.GetFileName(file) ); + } + + if ( basePathParts.Count == 1 && filePathParts.Count == 1) + { + return filePathParts.Single(); + } + + if ( basePathParts.Count == 0) + { + filePathParts.Insert(0, "."); + return String.Join( Path.DirectorySeparatorChar, filePathParts ); + } + + if ( basePathParts.Count > filePathParts.Count ) + { + return String.Join( Path.DirectorySeparatorChar, Enumerable.Repeat("..", basePathParts.Count - filePathParts.Count).Concat(filePathParts)); + } + + throw new NotSupportedException(); + } /// /// If a file has the read-only attribute, this method will remove it. diff --git a/src/WebCompiler/Node/prepare.cmd b/src/WebCompiler/Node/prepare.cmd index 5cc9ee48..d70e645e 100644 --- a/src/WebCompiler/Node/prepare.cmd +++ b/src/WebCompiler/Node/prepare.cmd @@ -6,4 +6,4 @@ del /q node_modules.7z del /q 7z.exe del /q 7z.dll -del /q prepare.cmd +del /q prepare.cmd \ No newline at end of file diff --git a/src/WebCompiler/Node/prepare.sh b/src/WebCompiler/Node/prepare.sh new file mode 100644 index 00000000..c517a12b --- /dev/null +++ b/src/WebCompiler/Node/prepare.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +7z x -y node_modules.7z +rm node_modules.7z + +rm prepare.sh diff --git a/src/WebCompiler/WebCompiler.csproj b/src/WebCompiler/WebCompiler.csproj index d9f67426..b773055d 100644 --- a/src/WebCompiler/WebCompiler.csproj +++ b/src/WebCompiler/WebCompiler.csproj @@ -2,7 +2,7 @@ Exe - net4.8;netstandard2.1;netcoreapp3.1 + netcoreapp3.1;net4.8;netstandard2.1 latest Web Compiler BuildWebCompiler2022 @@ -23,6 +23,7 @@ + @@ -36,6 +37,9 @@ + + +