lisp-rails-view 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: dbdddd6688a527855ed9e36b3219ae465820bbaa
4
+ data.tar.gz: 09f2e4529a22af4ebccd5e28e8b6269a2b6778d9
5
+ SHA512:
6
+ metadata.gz: a98ac529566451e8d0490ed66f4d5ab2c4e7e58b963d6645815402529c7d1fe6fb8fdcbd9bf3ebcd314c3da3c39dac234cf9ff5c1a25753502ba78bd013891b1
7
+ data.tar.gz: 102a8232c486c37e09d543190b0f375a752bfaf5d6adeb087019632e7b3f33931b4135e65b1e8223c60f47b9cfd772817ed8bb595358089345eea7282538dc9f
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *~
2
+ *.gem
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in lisp-rails-view.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 TAHARA Yoshinori
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,37 @@
1
+ # lisp-rails-view
2
+
3
+ lisp-rails-view is a templating engine for HTML.
4
+
5
+ ## Installation
6
+
7
+ Install SBCL:
8
+
9
+ sudo apt-get install sbcl
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'lisp-rails-view'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ ## Usage
20
+
21
+ index.html.lisp
22
+
23
+ ```
24
+ (:div#main
25
+ (:h3.title "title")
26
+ (:p#foo.bar "Hello"))
27
+ ```
28
+
29
+ see https://github.com/quek/lisp-rails-view/tree/master/examples
30
+
31
+ ## Contributing
32
+
33
+ 1. Fork it
34
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
35
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
36
+ 4. Push to the branch (`git push origin my-new-feature`)
37
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1 @@
1
+ (:p "パーシャルの中です。まみむめも。")
@@ -0,0 +1,99 @@
1
+ (:h1.title "lisp-rails-view Lisp ビューを書く")
2
+
3
+ (:h2 "イストール")
4
+
5
+ (:p "あらかじめ SBCL をインストールしておいてください。")
6
+
7
+ (:h2 "使い方")
8
+
9
+ (:h3 "基本")
10
+
11
+ ;; CL なのでこんにふうにコメントアウトできる
12
+ #+ni
13
+ (:pre (WITH-OUTPUT-TO-STRING (*STANDARD-OUTPUT*) (ROOM)))
14
+
15
+ (:p.warning "b__ は予約語なので使えません。")
16
+
17
+ "文字列はそのまま出力。<p>"
18
+
19
+ (:p "タグはキーワードで書く。")
20
+
21
+ (:p "(setf (readtable-case *readtable*) :preserve) しているので大文字で書くと CL"
22
+ (:br)
23
+ (IF (EVENP (GET-UNIVERSAL-TIME))
24
+ "偶数"
25
+ "奇数"))
26
+
27
+ (:h3 "エスケープ")
28
+
29
+ (:p "エスケープされるはず。<script>alert(\"hello\");</script>&\"'")
30
+
31
+ (:h3 "Ruby のコード")
32
+
33
+ (:p "ふつうに . かスペースです。")
34
+
35
+ (:div
36
+ (:p "(= @facilities first name) => " (= @facilities first name))
37
+ (:p "(= @facilities.first.name) => "(= @facilities.first.name))
38
+ (:p "(= @facilities[1] name) => "(= @facilities[1] name)))
39
+
40
+ (:p "引数は括弧でかこってください。CL の都合上 : は \\ でエスケープしてください。")
41
+
42
+ (:p "(= Time.now) => "(= Time.now))
43
+ (:p "(= Time.now.to_s (\:datetime)) => "(= Time.now.to_s (\:datetime)))
44
+ (:p "(= @facilities.map (&\:name)) => "(= @facilities.map (&\:name)))
45
+ (:p "(= @facilities map (&\:name) join (\"、\")) => "(= @facilities map (&\:name) join ("、")))
46
+
47
+
48
+ (:h3 "each")
49
+
50
+ (:p "ブロックは lambda にしてください。")
51
+
52
+ (:p
53
+ (:pre "(:ul
54
+ (@facilities each (lambda (facility) (:li (= facility.name)))))")
55
+ (:ul
56
+ (@facilities each (lambda (facility)
57
+ (:li (= facility.name))))))
58
+
59
+ (:h3 "if")
60
+
61
+ (:p "if もなんとか書けます。")
62
+
63
+ (:p
64
+ (:pre
65
+ "(if (Time now to_i even?)
66
+ \"偶数\"
67
+ \"奇数\")")
68
+ (if (Time now to_i even?)
69
+ "偶数"
70
+ "奇数"))
71
+
72
+
73
+ (:h3 "render")
74
+
75
+ (:p "パーシャばもなんとか。")
76
+
77
+ (:p (:pre "(= render (\"partial\"))"))
78
+ (= render ("partial"))
79
+
80
+
81
+ (:h3 "form")
82
+
83
+ (:p "フォーム")
84
+
85
+ (:p (:pre "(= form_for (Facility first)
86
+ (lambda (f)
87
+ (:p "フォームの中です<p>")
88
+ (:p
89
+ (= f label (\:name))
90
+ (= f text_field (\:name))
91
+ (= f submit))))"))
92
+
93
+ (= form_for (Facility first)
94
+ (lambda (f)
95
+ (:p "フォームの中です<p>")
96
+ (:p
97
+ (= f label (\:name))
98
+ (= f text_field (\:name))
99
+ (= f submit))))
@@ -0,0 +1,6 @@
1
+ (:html
2
+ (:head
3
+ (:meta :charset "utf-8")
4
+ (:title "lisp-rails-view Lisp ビューを書く"))
5
+ (:body
6
+ (= yield)))
@@ -0,0 +1,39 @@
1
+ require "lisp-rails-view/version"
2
+
3
+ module LispRailsView
4
+ class Railtie < ::Rails::Railtie
5
+ initializer :lisp do |app|
6
+ ActiveSupport.on_load :action_view do
7
+ ActionView::Template.register_template_handler :lisp, LispHandler
8
+ end
9
+ end
10
+ end
11
+
12
+ class LispHandler
13
+
14
+ LISP = File.expand_path('../../lisp/lisp-rails-view.lisp', __FILE__)
15
+
16
+ def self.call(template)
17
+ file = template.identifier
18
+ x = `sbcl --script #{LISP} #{file}`
19
+ code = <<EOT
20
+ [].tap do |b__|
21
+ def b__.push(x)
22
+ if x.is_a?(Array)
23
+ x.map do |y|
24
+ push(y)
25
+ end
26
+ else
27
+ super(x.html_safe? ? x : ERB::Util.h(x))
28
+ end
29
+ end
30
+ #{x}
31
+ end.flatten.join.html_safe
32
+ EOT
33
+ Rails.logger.debug('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$')
34
+ Rails.logger.debug(code)
35
+ Rails.logger.debug('$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$')
36
+ code
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,3 @@
1
+ module LispRailsView
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/lisp-rails-view/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["TAHARA Yoshinori"]
6
+ gem.email = ["read.eval.print@gmail.com"]
7
+ gem.description = %q{lisp-rails-view is a templating engine for HTML.}
8
+ gem.summary = %q{lisp-rails-view is a templating engine for HTML.}
9
+ gem.homepage = "https://github.com/quek/lisp-rails-view"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "lisp-rails-view"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = LispRailsView::VERSION
17
+
18
+ gem.add_development_dependency 'bundler'
19
+ gem.add_development_dependency 'rake'
20
+ end
@@ -0,0 +1,229 @@
1
+ (defpackage :lisp-rails-view
2
+ (:use :cl))
3
+
4
+ (in-package :lisp-rails-view)
5
+
6
+ (defvar *buffer* nil)
7
+
8
+ (defclass raw ()
9
+ ((value :initarg :value :accessor value)))
10
+
11
+ (defclass raw= (raw) ())
12
+
13
+ (defclass html-safe ()
14
+ ((value :initarg :value :accessor value)))
15
+
16
+ (defun raw (x)
17
+ (make-instance 'raw :value x))
18
+
19
+ (defun raw= (x)
20
+ (make-instance 'raw= :value x))
21
+
22
+ (defun html-safe (x)
23
+ (make-instance 'html-safe :value x))
24
+
25
+ (eval-when (:compile-toplevel :load-toplevel :execute)
26
+ (defmacro with-reader (&body body)
27
+ `(let ((*readtable* (copy-readtable nil)))
28
+ (setf (readtable-case *readtable*) :preserve)
29
+ ,@body)))
30
+
31
+ (defun call (template)
32
+ (with-reader (%call template))
33
+ (flush-buffer t))
34
+
35
+ (defun %call (template)
36
+ (with-open-file (in template)
37
+ (loop for form = (read in nil nil)
38
+ while form
39
+ do (%eval form))))
40
+
41
+ (defun flush-buffer (stream)
42
+ ;;TODO constant の連結
43
+ (loop for x in (nreverse *buffer*)
44
+ do (format stream "~a~%" (to-ruby-exp x))))
45
+
46
+ (defun emit (x)
47
+ (push x *buffer*))
48
+
49
+ (defun to-s (x)
50
+ (with-output-to-string (out)
51
+ (write-char #\" out)
52
+ (loop for c across (princ-to-string x)
53
+ do (cond ((char= c #\")
54
+ (write-string "\\\"" out))
55
+ (t
56
+ (write-char c out))))
57
+ (write-char #\" out)))
58
+
59
+ (defun to-ruby-token (x)
60
+ (typecase x
61
+ (string x
62
+ (to-s x))
63
+ (t x)))
64
+
65
+ (defmethod to-ruby-exp (x)
66
+ (with-output-to-string (out)
67
+ (write-string "b__.push(" out)
68
+ (write-string (to-s x) out)
69
+ (write-string ")" out)))
70
+
71
+ (defmethod to-ruby-exp ((x number))
72
+ (to-ruby-exp (princ-to-string x)))
73
+
74
+ (defmethod to-ruby-exp ((x raw))
75
+ (value x))
76
+
77
+ (defmethod to-ruby-exp ((x raw=))
78
+ (format nil "b__.push(~a)" (value x)))
79
+
80
+ (defmethod to-ruby-exp ((x html-safe))
81
+ (format nil "b__.push(~a.html_safe)" (to-s (value x))))
82
+
83
+
84
+ (defmethod %eval (x)
85
+ (emit x))
86
+
87
+ (defmethod %eval ((x null)))
88
+
89
+ (defmethod %eval ((x cons))
90
+ (cond ((eq '= (car x))
91
+ (emit (raw= (make-ruby-form (cdr x) t))))
92
+ ((keywordp (car x))
93
+ (process-tag x))
94
+ ((and (symbolp (car x))
95
+ (fboundp (car x)))
96
+ (emit (eval x)))
97
+ (t
98
+ (emit (raw (make-ruby-form x))))))
99
+
100
+ (defun process-tag (form)
101
+ (multiple-value-bind (tag id classes) (parse-tag (car form))
102
+ (multiple-value-bind (attributes body /-p) (parse-tag-args (cdr form))
103
+ (when classes
104
+ (let ((kv (assoc "class" attributes :test #'string=)))
105
+ (when kv
106
+ (setf (cdr kv) `(append ',classes
107
+ (ensure-list ,(cdr kv)))
108
+ classes nil))))
109
+ (emit (html-safe (with-output-to-string (out)
110
+ (format out "<~a" tag)
111
+ (when id
112
+ (format out " id=\"~a\"" id))
113
+ (when classes
114
+ (format out " class=\"~{~a~^ ~}\"" classes))
115
+ (loop for (k . v) in attributes do
116
+ (if (constantp v)
117
+ (if (eq v t)
118
+ (format out " ~a" k)
119
+ (format out " ~a=\"~a\"" k v))
120
+ (format out "#{~a == true ? \"~a\" : \"~a=\"~a\"\"}" v k k v)))
121
+ (if /-p
122
+ (write-string " />" out)
123
+ (write-string ">" out)))))
124
+ (loop for i in body
125
+ do (%eval i))
126
+ (emit (html-safe (format nil "</~a>" tag))))))
127
+
128
+ (defun parse-tag (tag)
129
+ (let* ((str (string-downcase (symbol-name tag)))
130
+ (p# (position #\# str))
131
+ (p. (position #\. str)))
132
+ (cond ((and (not p#) (not p.))
133
+ str)
134
+ ((and p# (not p.))
135
+ (values (subseq str 0 p#)
136
+ (subseq str (1+ p#))))
137
+ ((and (not p#) p.)
138
+ (values (subseq str 0 p.)
139
+ nil
140
+ #1=(loop for start = (1+ p.) then (1+ end)
141
+ for end = (position #\. str :start start)
142
+ collect (subseq str start end)
143
+ unless end
144
+ do (loop-finish))))
145
+ (t
146
+ (values (subseq str 0 p#)
147
+ (subseq str (1+ p#) p.)
148
+ #1#)))))
149
+
150
+ (defun parse-tag-args (args)
151
+ (let (attributes)
152
+ (labels ((f (args)
153
+ (if (and (consp args)
154
+ (keywordp (car args)))
155
+ (progn
156
+ (push (cons (string-downcase (car args)) (cadr args)) attributes)
157
+ (f (cddr args)))
158
+ (values (nreverse attributes)
159
+ args
160
+ (if (atom args)
161
+ args
162
+ (cdr (last args)))))))
163
+ (f args))))
164
+
165
+ (defun blockp (form)
166
+ (and (consp (car (last form)))
167
+ (string-equal "lambda" (caar (last form)))))
168
+
169
+ (defun make-ruby-form (form &optional new-buffer-p)
170
+ (with-output-to-string (out)
171
+ (let* ((blockp (blockp form))
172
+ (block-form (and blockp (cdar (last form))))
173
+ (main-form (if blockp (butlast form) form)))
174
+ (make-ruby-main-form (car main-form) (cdr main-form) out)
175
+ (when block-form
176
+ (format out "{~a}" (make-ruby-block block-form new-buffer-p))))))
177
+
178
+ (defmethod make-ruby-main-form (first rest out)
179
+ (format out "~a" (to-ruby-token first))
180
+ (loop for i in rest
181
+ do (if (consp i)
182
+ (format out "(~{~a~^, ~})" (mapcar #'make-ruby-form (list i)))
183
+ (progn
184
+ (write-char #\. out)
185
+ (format out "~a" (to-ruby-token i))))))
186
+
187
+ (defmethod make-ruby-main-form ((first (eql '|if|)) rest out)
188
+ (format out "if ~a~%~aelse~%~aend"
189
+ (make-ruby-form (car rest))
190
+ (make-ruby-block-body (ensure-list (cadr rest)))
191
+ (make-ruby-block-body (ensure-list (caddr rest)))))
192
+
193
+ (defun make-ruby-block (form &optional new-buffer-p)
194
+ (with-output-to-string (out)
195
+ (let ((args (car form))
196
+ (body (make-ruby-block-body (cdr form))))
197
+ (when args
198
+ (format out "|~{~a~^, ~}|~%" args))
199
+ (if new-buffer-p
200
+ (format out "
201
+ [].tap do |b__|
202
+ def b__.push(x)
203
+ if x.is_a?(Array)
204
+ x.map do |y|
205
+ push(y)
206
+ end
207
+ else
208
+ super(x.html_safe? ? x : ERB::Util.h(x))
209
+ end
210
+ end
211
+ ~a
212
+ end.flatten.join.html_safe~%" body)
213
+ (format out "~a" body)))))
214
+
215
+ (defun make-ruby-block-body (form)
216
+ (let ((*buffer* nil))
217
+ (loop for i in form
218
+ do (%eval i))
219
+ (with-output-to-string (out)
220
+ (flush-buffer out))))
221
+
222
+ (defun ensure-list (x)
223
+ (if (consp x)
224
+ x
225
+ (list x)))
226
+
227
+ (let ((template (cadr sb-ext:*posix-argv*)))
228
+ (when template
229
+ (call template)))
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lisp-rails-view
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - TAHARA Yoshinori
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-12-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: lisp-rails-view is a templating engine for HTML.
42
+ email:
43
+ - read.eval.print@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - Gemfile
50
+ - LICENSE
51
+ - README.md
52
+ - Rakefile
53
+ - examples/_partial.html.lisp
54
+ - examples/index.html.lisp
55
+ - examples/layout.html.lisp
56
+ - lib/lisp-rails-view.rb
57
+ - lib/lisp-rails-view/version.rb
58
+ - lisp-rails-view.gemspec
59
+ - lisp/lisp-rails-view.lisp
60
+ homepage: https://github.com/quek/lisp-rails-view
61
+ licenses: []
62
+ metadata: {}
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project:
79
+ rubygems_version: 2.2.1
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: lisp-rails-view is a templating engine for HTML.
83
+ test_files: []