smallvictories 0.0.15 → 0.0.16

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f731d5d6df1739579b31fcbe694c4795a0f640a4
4
- data.tar.gz: 5a5bb5a7266da54154008320f0ca1a0fa96e507c
3
+ metadata.gz: 12382dc9fd1f3d1688534c4a2df59eaaa1eab52b
4
+ data.tar.gz: 0da0a7dc2013e224a60376cd9f54303e315b1372
5
5
  SHA512:
6
- metadata.gz: 245511be3d12b3d8f3971474247a9c353437609c93b6f4283468462382e0e10e2fd607691d749605ca8df98d0515eba22e2d3ba43c7a5162e0a7cb9a8b4a368d
7
- data.tar.gz: 6ce3b4d002e499b90c6513ffe1034801fa8d9113ec9dec96e0fcff41ea9d7c26f11079355d33a8787e2c74b96e0fffd383f92a34a6535d593817b1afd6358ab7
6
+ metadata.gz: 4e8ef9f37f4da27baff4b8f5fb3ffa625a6256d557dc9c96b196729ebfb59437af11e5c5f9cb39ef074ddcc65e9362afffb2941a8726be0508cfbe7bc36ab7ea
7
+ data.tar.gz: a6ad93cdae7983dfd6eb9b066c335dfa13b6325e8faae02b453d2854c72f0b5a36a4a1697299424d9f0dade517dcce78d9b998ec6c66ce376c5adf073bef669b
data/bin/sv CHANGED
@@ -12,6 +12,7 @@ def help
12
12
  deploy Minify and copy files to deploy folder
13
13
  inline Inline CSS in your HTML files
14
14
  minify Minify files for production
15
+ server Run Small Victories local HTML development server
15
16
  watch Watch for changes and compile files
16
17
  help Prints this help document
17
18
  version Prints the small victories gem version
@@ -68,6 +69,12 @@ def minify
68
69
  compiler.minify_js
69
70
  end
70
71
 
72
+ def server
73
+ config = SmallVictories::Configuration.new
74
+ server = SmallVictories::Server.new(config: config)
75
+ server.run
76
+ end
77
+
71
78
  def watch
72
79
  compile
73
80
  config = SmallVictories::Configuration.new
@@ -89,6 +96,10 @@ when 'deploy'
89
96
  deploy ARGV[1]
90
97
  when 'inline'
91
98
  inline
99
+ when 'minify'
100
+ minify
101
+ when 'server'
102
+ server
92
103
  when 'watch'
93
104
  watch
94
105
  else
@@ -5,10 +5,12 @@ require "smallvictories/version"
5
5
  require "smallvictories/constants"
6
6
  require "smallvictories/logger"
7
7
  require "smallvictories/configuration"
8
+ require "smallvictories/site_file"
8
9
  require "smallvictories/builder"
9
10
  require "smallvictories/compiler"
10
11
  require "smallvictories/deployer"
11
12
  require "smallvictories/watcher"
13
+ require "smallvictories/server"
12
14
  require "sassc/compressor"
13
15
  require "sassc/functions"
14
16
  require "sassc/importer"
@@ -156,6 +156,7 @@ module SmallVictories
156
156
  end
157
157
 
158
158
  def sprite
159
+ SmallVictories.logger.debug "Spriting"
159
160
  sprite_directory = File.join(config.full_source_path, config.source_sprite)
160
161
  return unless Dir.exists?(sprite_directory)
161
162
  css = "@import 'rails-sass-images';\n"
@@ -1,6 +1,6 @@
1
1
  module SmallVictories
2
2
  CONFIG_FILE = '_sv_config.yml'
3
- GUARD_FILE = '.sv_guardfile'
3
+ GUARD_FILE = 'Guardfile'
4
4
  DEFAULT_SOURCE = '_sv'
5
5
  DEFAULT_DEPLOY = ''
6
6
  DEFAULT_DESTINATION = ''
@@ -12,7 +12,7 @@ module SmallVictories
12
12
 
13
13
  def copy folder=nil
14
14
  folder ||= config.deploy
15
- deploy_path = File.join(ROOT, folder)
15
+ deploy_path = File.join(ROOT, "#{folder}/")
16
16
  begin
17
17
  Find.find(config.full_destination_path) do |source|
18
18
  Find.prune if self.ignore_files.include?(File.basename(source))
@@ -29,7 +29,7 @@ module SmallVictories
29
29
  end
30
30
 
31
31
  def ignore_files
32
- ['.git', config.source, CONFIG_FILE, GUARD_FILE]
32
+ ['.DS_Store', '.git', '.gitignore', config.source, CONFIG_FILE, GUARD_FILE]
33
33
  end
34
34
  end
35
35
  end
@@ -0,0 +1,155 @@
1
+ require 'socket'
2
+ require 'uri'
3
+ require 'liquid'
4
+ require 'mime-types'
5
+ require 'sass'
6
+ require 'sassc'
7
+
8
+
9
+ module SmallVictories
10
+ class Server
11
+ attr_accessor :config, :socket, :server
12
+
13
+ # Files will be served from this directory
14
+ WEB_ROOT = './'
15
+ TEMP_FILE = './.sv_temp'
16
+
17
+ # Treat as binary data if content type cannot be found
18
+ DEFAULT_CONTENT_TYPE = 'application/octet-stream'
19
+
20
+ # This helper function parses the extension of the
21
+ # requested file and then looks up its content type.
22
+
23
+ def initialize attributes={}
24
+ self.config = attributes[:config]
25
+ end
26
+
27
+ def content_type(path)
28
+ if ext = File.extname(path).split(".").last
29
+ MIME::Types.type_for(ext).first.to_s
30
+ else
31
+ 'text/html'
32
+ end
33
+ end
34
+
35
+ # This helper function parses the Request-Line and
36
+ # generates a path to a file on the server.
37
+
38
+ def requested_file(request_line)
39
+ request_uri = request_line.split(" ")[1]
40
+ path = URI.unescape(URI(request_uri).path)
41
+
42
+ clean = []
43
+
44
+ # Split the path into components
45
+ parts = path.split("/")
46
+
47
+ parts.each do |part|
48
+ # skip any empty or current directory (".") path components
49
+ next if part.empty? || part == '.'
50
+ # If the path component goes up one directory level (".."),
51
+ # remove the last clean component.
52
+ # Otherwise, add the component to the Array of clean components
53
+ part == '..' ? clean.pop : clean << part
54
+ end
55
+
56
+ # return the web root joined to the clean path
57
+ File.join(WEB_ROOT, *clean)
58
+ end
59
+
60
+ # This helper function saves the string to
61
+ # a temp file and streams it
62
+
63
+ def render_file file, content_type=nil
64
+ socket.print "HTTP/1.1 200 OK\r\n" +
65
+ "Content-Type: #{content_type || content_type(file)}\r\n" +
66
+ "Content-Length: #{file.size}\r\n" +
67
+ "Connection: close\r\n"
68
+
69
+ socket.print "\r\n"
70
+
71
+ # write the contents of the file to the socket
72
+ IO.copy_stream(file, socket)
73
+ end
74
+
75
+ def render_string string, content_type=nil
76
+ File.open(TEMP_FILE, "w") do |f|
77
+ f.write(string)
78
+ f.close
79
+ end
80
+
81
+ File.open(TEMP_FILE, "rb") { |f| render_file(f, content_type) }
82
+ end
83
+
84
+ def render_stylesheet
85
+ if File.exist?(File.join(WEB_ROOT, '_sv_custom.scss'))
86
+ begin
87
+ engine = Sass::Engine.new(File.open(File.join(WEB_ROOT, '_sv_custom.scss')).read, syntax: :scss)
88
+ render_string(engine.render, 'text/css')
89
+ rescue => e
90
+ socket.print e
91
+ end
92
+ elsif File.exist?(File.join(WEB_ROOT, '_sv_custom.sass'))
93
+ begin
94
+ engine = Sass::Engine.new(File.open(File.join(WEB_ROOT, '_sv_custom.sass')).read, syntax: :sass)
95
+ render_string(engine.render, 'text/css')
96
+ rescue => e
97
+ socket.print e
98
+ end
99
+ elsif File.exist?(File.join(WEB_ROOT, '_sv_custom.css'))
100
+ # Open _sv_custom.css
101
+ File.open(File.join(WEB_ROOT, '_sv_custom.css'), "rb") do |file|
102
+ render_file(file)
103
+ end
104
+ end
105
+ end
106
+
107
+ def run
108
+ # Except where noted below, the general approach of
109
+ # handling requests and generating responses is
110
+ # similar to that of the "Hello World" example
111
+ # shown earlier.
112
+
113
+ @server = TCPServer.new('localhost', 2345)
114
+
115
+ loop do
116
+ @socket = @server.accept
117
+ request_line = socket.gets
118
+ socket.close if request_line == nil
119
+
120
+ STDERR.puts request_line
121
+
122
+ path = requested_file(request_line)
123
+ path = File.join(path, 'index.html') if File.directory?(path)
124
+
125
+ if path == File.join(WEB_ROOT, '_sv_custom.css')
126
+ render_stylesheet
127
+ elsif File.exist?(path) && !File.directory?(path)
128
+ File.open(path, "rb") do |file|
129
+ if File.extname(path) == '.html'
130
+ # parse liquid
131
+ template = Liquid::Template.parse(file.read, error_mode: :warn)
132
+ render_string(template.render(SiteFile.files_hash))
133
+ else
134
+ render_file(file)
135
+ end
136
+ end
137
+ else
138
+ message = "File not found\n"
139
+
140
+ # respond with a 404 error code to indicate the file does not exist
141
+ socket.print "HTTP/1.1 404 Not Found\r\n" +
142
+ "Content-Type: text/plain\r\n" +
143
+ "Content-Length: #{message.size}\r\n" +
144
+ "Connection: close\r\n"
145
+
146
+ socket.print "\r\n"
147
+
148
+ socket.print message
149
+ end
150
+
151
+ socket.close
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,104 @@
1
+ module SmallVictories
2
+ class SiteFile
3
+ attr_accessor :path
4
+
5
+ def self.files_hash folder_path=SmallVictories::Server::WEB_ROOT
6
+ hash = {}
7
+
8
+ Dir.glob(File.join(folder_path, '*')) do |path|
9
+ next if path == '.' or path == '..'
10
+ file = SiteFile.new path
11
+ key = path.gsub(folder_path, '').gsub(/^\//, '').gsub('/', '.')
12
+ key = key.gsub(/\.#{file.extension}$/, '')
13
+
14
+ if Dir.exists?(path)
15
+ hash[key] = SiteFile.files_hash(path)
16
+ else
17
+ hash[key] = file.downloadable? ? path : file.read
18
+ end
19
+ end
20
+
21
+ hash
22
+ end
23
+
24
+ def initialize path
25
+ @path = path
26
+ end
27
+
28
+ def extension
29
+ File.extname(path).gsub(/^./,'')
30
+ end
31
+
32
+ def file
33
+ File.open(path)
34
+ end
35
+
36
+ def read
37
+ file.read
38
+ end
39
+
40
+ def file_type
41
+ MIME::Types.type_for('css')
42
+ end
43
+
44
+ def asset?
45
+ audio? or image? or video? or css? or js?
46
+ end
47
+
48
+ def media_asset?
49
+ audio? or image? or video?
50
+ end
51
+
52
+ def audio?
53
+ file_type =~ /audio/ ? true : false
54
+ end
55
+
56
+ def css?
57
+ extension == 'css'
58
+ end
59
+
60
+ def downloadable?
61
+ asset? || pdf?
62
+ end
63
+
64
+ def image?
65
+ file_type =~ /image/ ? true : false
66
+ end
67
+
68
+ def js?
69
+ extension == 'js'
70
+ end
71
+
72
+ def video?
73
+ file_type =~ /video/ ? true : false
74
+ end
75
+
76
+ def render
77
+ read
78
+ end
79
+
80
+ def text?
81
+ extension == 'txt'
82
+ end
83
+
84
+ def html?
85
+ extension == 'html'
86
+ end
87
+
88
+ def markdown?
89
+ extension == 'md'
90
+ end
91
+
92
+ def webloc?
93
+ extension == 'webloc' || extension.downcase == 'url'
94
+ end
95
+
96
+ def pdf?
97
+ extension == 'pdf'
98
+ end
99
+
100
+ def text_based_file?
101
+ markdown? || text? || html? || webloc? || pdf?
102
+ end
103
+ end
104
+ end
@@ -1,3 +1,3 @@
1
1
  module SmallVictories
2
- VERSION = "0.0.15"
2
+ VERSION = "0.0.16"
3
3
  end
@@ -40,14 +40,18 @@ module SmallVictories
40
40
  SmallVictories.logger.debug "👋"
41
41
  SmallVictories.logger.debug "👀"
42
42
 
43
- pid = Process.fork { system('guard -i --guardfile .sv_guardfile') }
44
- Process.detach(pid)
43
+ if File.exists?('Guardfile')
44
+ pid = Process.fork { system('guard -i') }
45
+ Process.detach(pid)
46
+ end
45
47
 
46
48
  listener = build_listener
47
49
  listener.start
48
50
 
49
51
  trap("INT") do
50
- Process.kill "TERM", pid
52
+ if File.exists?('Guardfile')
53
+ Process.kill "TERM", pid
54
+ end
51
55
  listener.stop
52
56
  puts "✋ Halting auto-regeneration."
53
57
  exit 0
@@ -34,6 +34,7 @@ Gem::Specification.new do |spec|
34
34
  spec.add_runtime_dependency 'sprite-factory', '~> 1.7'
35
35
  spec.add_runtime_dependency 'rmagick', '~> 2.15'
36
36
  spec.add_runtime_dependency 'rails-sass-images', '~> 1.0'
37
+ spec.add_runtime_dependency 'mime-types'
37
38
 
38
39
  spec.add_development_dependency "bundler", "~> 1.7"
39
40
  spec.add_development_dependency "rake", "~> 10.0"
@@ -2,13 +2,12 @@ require 'spec_helper'
2
2
 
3
3
  describe SmallVictories do
4
4
  let(:builder) { SmallVictories::Builder.new(config: SmallVictories::Configuration.new) }
5
- let(:files) { %w(fixtures/new/_sv_config.yml fixtures/new/.sv_guardfile fixtures/new/_sv/index.liquid fixtures/new/_sv/application.scss fixtures/new/_sv/application.js fixtures/new/_sv/_includes/_head.liquid fixtures/new/_sv/_layout.liquid fixtures/new/_sv/_sprite/empty.png) }
5
+ let(:files) { %w(fixtures/new/_sv_config.yml fixtures/new/Guardfile fixtures/new/_sv/index.liquid fixtures/new/_sv/application.scss fixtures/new/_sv/application.js fixtures/new/_sv/_includes/_head.liquid fixtures/new/_sv/_layout.liquid fixtures/new/_sv/_sprite/empty.png) }
6
6
 
7
7
  context 'with folder' do
8
8
  it 'sets up default files' do
9
9
  builder.setup 'spec/fixtures/new'
10
10
  files.each do |file|
11
- puts file
12
11
  expect(File.exists?(file)).to eq true
13
12
  end
14
13
  end
@@ -128,7 +128,7 @@ describe SmallVictories do
128
128
 
129
129
  it 'inlines the compiled files' do
130
130
  compiler.inline_html
131
- expect(File.open(destination_html).read).to include "<p style=\"font-size: 12px\">Hello Email Friend</p>"
131
+ expect(File.open(destination_html).read).to include "<p style=\"font-size: 12px;\">Hello Email Friend</p>"
132
132
  end
133
133
  end
134
134
 
@@ -0,0 +1,17 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta http-equiv="x-ua-compatible" content="ie=edge">
6
+ <title>Small Victories</title>
7
+ <meta name="description" content="{{ site.description }}">
8
+ <meta name="viewport" content="width=device-width, initial-scale=1">
9
+ <link rel="icon" type="image/png" href="favicon.png">
10
+ <link rel="stylesheet" href="_sv_custom.css">
11
+ </head>
12
+ <body>
13
+ <h1>{{ settings.title }}</h1>
14
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
15
+ <script src="_sv_custom.js"></script>
16
+ </body>
17
+ </html>
@@ -0,0 +1 @@
1
+ My Title
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe SmallVictories::SiteFile do
4
+ context 'with folder' do
5
+ it 'creates files hash' do
6
+ files = SmallVictories::SiteFile.files_hash 'fixtures/liquid'
7
+ expect(files['settings']['title']).to eq "My Title\n"
8
+ end
9
+ end
10
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smallvictories
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.15
4
+ version: 0.0.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Dijkstra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-14 00:00:00.000000000 Z
11
+ date: 2016-11-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: autoprefixer-rails
@@ -234,6 +234,20 @@ dependencies:
234
234
  - - "~>"
235
235
  - !ruby/object:Gem::Version
236
236
  version: '1.0'
237
+ - !ruby/object:Gem::Dependency
238
+ name: mime-types
239
+ requirement: !ruby/object:Gem::Requirement
240
+ requirements:
241
+ - - ">="
242
+ - !ruby/object:Gem::Version
243
+ version: '0'
244
+ type: :runtime
245
+ prerelease: false
246
+ version_requirements: !ruby/object:Gem::Requirement
247
+ requirements:
248
+ - - ">="
249
+ - !ruby/object:Gem::Version
250
+ version: '0'
237
251
  - !ruby/object:Gem::Dependency
238
252
  name: bundler
239
253
  requirement: !ruby/object:Gem::Requirement
@@ -290,23 +304,8 @@ files:
290
304
  - LICENSE.txt
291
305
  - README.md
292
306
  - Rakefile
293
- - _sv/_includes/_snippet.liquid
294
- - _sv/_javascripts/scripts.coffee
295
- - _sv/_javascripts/scripts.js
296
- - _sv/_layout.liquid
297
- - _sv/_sprite/.gitkeep
298
- - _sv/_sprite/blank.png
299
- - _sv/_stylesheets/bootstrap.scss
300
- - _sv/_stylesheets/extra.scss
301
- - _sv/_stylesheets/stylesheet.scss
302
- - _sv/application.css
303
- - _sv/application.js
304
- - _sv/index.html
305
- - _sv_config.yml
306
307
  - _sv_custom.css
307
308
  - _sv_custom.js
308
- - application.css
309
- - application.js
310
309
  - bin/sv
311
310
  - index.html
312
311
  - lib/sassc/compressor.rb
@@ -320,6 +319,8 @@ files:
320
319
  - lib/smallvictories/constants.rb
321
320
  - lib/smallvictories/deployer.rb
322
321
  - lib/smallvictories/logger.rb
322
+ - lib/smallvictories/server.rb
323
+ - lib/smallvictories/site_file.rb
323
324
  - lib/smallvictories/version.rb
324
325
  - lib/smallvictories/watcher.rb
325
326
  - smallvictories.gemspec
@@ -355,6 +356,8 @@ files:
355
356
  - spec/fixtures/invalid/_layout.liquid
356
357
  - spec/fixtures/invalid/_sass/stylesheet.scss
357
358
  - spec/fixtures/invalid/index.html
359
+ - spec/fixtures/liquid/index.html
360
+ - spec/fixtures/liquid/settings/title.txt
358
361
  - spec/fixtures/source/_includes/_snippet.liquid
359
362
  - spec/fixtures/source/_javascripts/scripts.coffee
360
363
  - spec/fixtures/source/_javascripts/scripts.js
@@ -368,6 +371,7 @@ files:
368
371
  - spec/fixtures/source/application.css
369
372
  - spec/fixtures/source/application.js
370
373
  - spec/fixtures/source/index.html
374
+ - spec/site_file_spec.rb
371
375
  - spec/spec_helper.rb
372
376
  - src/Guardfile
373
377
  - src/config.yml
@@ -397,7 +401,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
397
401
  version: '0'
398
402
  requirements: []
399
403
  rubyforge_project:
400
- rubygems_version: 2.4.5
404
+ rubygems_version: 2.6.6
401
405
  signing_key:
402
406
  specification_version: 4
403
407
  summary: A command line utility for building websites.
@@ -434,6 +438,8 @@ test_files:
434
438
  - spec/fixtures/invalid/_layout.liquid
435
439
  - spec/fixtures/invalid/_sass/stylesheet.scss
436
440
  - spec/fixtures/invalid/index.html
441
+ - spec/fixtures/liquid/index.html
442
+ - spec/fixtures/liquid/settings/title.txt
437
443
  - spec/fixtures/source/_includes/_snippet.liquid
438
444
  - spec/fixtures/source/_javascripts/scripts.coffee
439
445
  - spec/fixtures/source/_javascripts/scripts.js
@@ -447,4 +453,5 @@ test_files:
447
453
  - spec/fixtures/source/application.css
448
454
  - spec/fixtures/source/application.js
449
455
  - spec/fixtures/source/index.html
456
+ - spec/site_file_spec.rb
450
457
  - spec/spec_helper.rb
@@ -1 +0,0 @@
1
- <p>My snippet</p>
@@ -1 +0,0 @@
1
- alert 'hi'
@@ -1 +0,0 @@
1
- console.log('hi');
@@ -1,3 +0,0 @@
1
- <html>
2
- {{content_for_layout}}
3
- </html>
File without changes
Binary file
@@ -1,4 +0,0 @@
1
- .bootstrap {
2
- color: black;
3
- box-sizing: content-box;
4
- }
@@ -1,3 +0,0 @@
1
- html {
2
- background: white;
3
- }
@@ -1,5 +0,0 @@
1
- body {
2
- div {
3
- background: red;
4
- }
5
- }
@@ -1,19 +0,0 @@
1
- /* Small Victories Sprockets File
2
- *
3
- * Any CSS and SCSS file within this directory and your sass directory
4
- * can be referenced here using a relative path.
5
- *
6
- * You're free to add application-wide styles to this file and they'll appear at the bottom of the
7
- * compiled file so the styles you add here take precedence over styles defined in any styles
8
- * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
9
- * file per style scope.
10
- *
11
- * Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
12
- * about supported directives.
13
- *
14
- *= require_tree .
15
- */
16
-
17
- p {
18
- font-size: 30px;
19
- }
@@ -1,14 +0,0 @@
1
- // Small Victories Sprockets File
2
- //
3
- // For more details see
4
- // https://github.com/rails/sprockets#the-directive-processor
5
- // Any JavaScript/Coffee file within this directory
6
- // can be referenced here using a relative path.
7
- //
8
- // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
9
- // compiled file.
10
- //
11
- // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
12
- // about supported directives.
13
- //
14
- //= require_tree .
@@ -1,2 +0,0 @@
1
- <h1>Index</h1>
2
- {% include 'snippet' %}
@@ -1,16 +0,0 @@
1
- source: '/my-source-folder/'
2
- destination: 'my-site-folder/'
3
- deploy: '../my-deploy-folder'
4
- source_stylesheet: 'my-stylesheet.css'
5
- source_javascript: 'my-javascript.js'
6
- source_sprite: 'my-sprite'
7
- destination_stylesheet: 'stylesheet.css'
8
- destination_javascript: 'javascript.js'
9
- destination_sprite_file: 'my-sprite.png'
10
- destination_sprite_style: 'my-sprite.css'
11
- layout: '_my-template.liquid'
12
- includes: 'snippets'
13
- compile_html: false
14
- compile_js: false
15
- compile_css: false
16
- compile_sprite: false
@@ -1,4 +0,0 @@
1
- html {
2
- background: red;
3
- box-sizing: content-box;
4
- }
@@ -1 +0,0 @@
1
- (function(){alert("hi")}).call(this),console.log("hi");