-
Notifications
You must be signed in to change notification settings - Fork 68
Expand file tree
/
Copy pathoutput.ex
More file actions
123 lines (102 loc) · 2.91 KB
/
output.ex
File metadata and controls
123 lines (102 loc) · 2.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
defmodule ElixirScript.Output do
@moduledoc false
alias ElixirScript.State, as: ModuleState
alias ESTree.Tools.{Builder, Generator}
@generated_name "Elixir.App.js"
@doc """
Takes outputs the JavaScript code in the specified output
"""
@spec execute([atom], pid) :: nil
def execute(modules, pid) do
modules = modules
|> Enum.filter(fn {_, info} -> Map.has_key?(info, :js_ast) end)
|> Enum.map(fn {_module, info} ->
info.js_ast
end
)
opts = ModuleState.get_compiler_opts(pid)
js_modules = ModuleState.js_modules(pid)
|> Enum.filter(fn
{_module, _name, nil} -> false
_ -> true
end)
|> Enum.map(fn
{module, name, path} ->
{module, name, Path.join(".", path)}
end)
bundle(modules, opts, js_modules)
|> output(Map.get(opts, :output), js_modules)
end
defp bundle(modules, opts, js_modules) do
modules
|> ElixirScript.Output.JSModule.compile(opts, js_modules)
|> List.wrap
|> Builder.program
|> prepare_js_ast
|> Generator.generate
|> concat
end
defp concat(code) do
bootstrap_code = get_bootstrap_js()
"'use strict';\n#{bootstrap_code}\n#{code}"
end
defp get_bootstrap_js() do
operating_path = Path.join([Mix.Project.build_path, "lib", "elixir_script", "priv"])
path = Path.join([operating_path, "build", "iife", "ElixirScript.Core.js"])
File.read!(path)
end
defp prepare_js_ast(js_ast) do
case js_ast do
modules when is_list(modules) ->
modules
|> Enum.reduce([], &(&2 ++ &1.body))
|> Builder.program
_ ->
js_ast
end
end
defp output(code, nil, _) do
code
end
defp output(code, :stdout, _) do
IO.puts(code)
end
defp output(code, path, js_modules) do
file_name = get_output_file_name(path)
if !File.exists?(Path.dirname(file_name)) do
File.mkdir_p!(Path.dirname(file_name))
end
apps = get_app_names()
output_dir = Path.dirname(file_name)
Enum.each(js_modules, fn({_, _, path}) ->
copy_javascript_module(apps, output_dir, path)
end)
File.write!(file_name, code)
end
def get_output_file_name(path) do
case Path.extname(path) do
".js" ->
path
_ ->
Path.join([path, @generated_name])
end
end
defp get_app_names() do
Mix.Project.config()[:app]
deps = Mix.Project.deps_paths()
|> Map.keys
[Mix.Project.config()[:app]] ++ deps
end
defp copy_javascript_module(apps, output_dir, js_module_path) do
Enum.each(apps, fn(app) ->
full_path = Path.join([:code.priv_dir(app), "elixir_script", js_module_path]) <> ".js"
if File.exists?(full_path) do
js_output_path = Path.join(output_dir, js_module_path) <> ".js"
if !File.exists?(Path.dirname(js_output_path)) do
File.mkdir_p!(Path.dirname(js_output_path))
end
File.cp(full_path, js_output_path)
end
end)
end
end