txprails 0.1.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.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +50 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/VERSION_NAME +1 -0
- data/bin/txprails +9 -0
- data/ext/txparse/Makefile +157 -0
- data/ext/txparse/extconf.rb +8 -0
- data/ext/txparse/test_txp.rb +65 -0
- data/ext/txparse/txparse.cpp +139 -0
- data/ext/txparse/txparse.h +15 -0
- data/ext/txparse/txparse_lib.cpp +191 -0
- data/ext/txparse/txparse_lib.h +17 -0
- data/ext/txparse/txparse_tag.cpp +109 -0
- data/ext/txparse/txparse_tag.h +7 -0
- data/lib/init_rails.rb +16 -0
- data/lib/txprails/commands.rb +88 -0
- data/lib/txprails/template.rb +29 -0
- data/lib/txprails/util.rb +44 -0
- data/lib/txprails/version.rb +64 -0
- data/lib/txprails.rb +44 -0
- data/test/helper.rb +10 -0
- data/test/test_txprails.rb +7 -0
- data/txprails.gemspec +73 -0
- metadata +91 -0
@@ -0,0 +1,191 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include "txparse.h"
|
3
|
+
|
4
|
+
//---------------------------------------------------------------------------
|
5
|
+
const string TXPDictSpaces = " \t\r\n";
|
6
|
+
const string TXPDictWordLim = " \t\r\n,<>/=";
|
7
|
+
const string TXPDictSingleQuote = "'";
|
8
|
+
const string TXPDictDoubleQuote = "\"";
|
9
|
+
|
10
|
+
string txp_domain_str = "dmstk";
|
11
|
+
|
12
|
+
//---------------------------------------------------------------------------
|
13
|
+
static bool txp_isspace(string::const_iterator iter)
|
14
|
+
{
|
15
|
+
return find(TXPDictSpaces.begin(), TXPDictSpaces.end(), *iter) != TXPDictSpaces.end();
|
16
|
+
}
|
17
|
+
|
18
|
+
//---------------------------------------------------------------------------
|
19
|
+
static bool txp_valid_chars(
|
20
|
+
string::const_iterator iter,
|
21
|
+
string::const_iterator end
|
22
|
+
)
|
23
|
+
{
|
24
|
+
if (*iter == '/') { iter++; end++; }
|
25
|
+
for (; iter != end; ++iter) {
|
26
|
+
if (::isspace(*iter)) return false;
|
27
|
+
if (*iter == ':') return true;
|
28
|
+
if (!::isalpha(*iter)) return false;
|
29
|
+
}
|
30
|
+
return false; // No se encontró los dos puntos...
|
31
|
+
}
|
32
|
+
|
33
|
+
//---------------------------------------------------------------------------
|
34
|
+
string::const_iterator txp_find_tag(
|
35
|
+
string::const_iterator iter,
|
36
|
+
string::const_iterator end
|
37
|
+
)
|
38
|
+
{
|
39
|
+
// Encontramos un TAG de plantilla cuando tengamos "<" + [a-z]{3} + ":"
|
40
|
+
// O también cuando tengamos "</" ya que es de cierre...
|
41
|
+
while (iter != end) {
|
42
|
+
if ((*iter == '<') && (end - iter > 5) && txp_valid_chars(iter+1, iter+7))
|
43
|
+
return iter;
|
44
|
+
++iter;
|
45
|
+
}
|
46
|
+
return iter;
|
47
|
+
}
|
48
|
+
|
49
|
+
//---------------------------------------------------------------------------
|
50
|
+
string::const_iterator txp_find_close(
|
51
|
+
string::const_iterator iter,
|
52
|
+
string::const_iterator end
|
53
|
+
)
|
54
|
+
{
|
55
|
+
// Encontramos un final de TAG cuando tengamos ">"
|
56
|
+
for (; iter != end; ++iter) {
|
57
|
+
if (*iter == '>') return iter+1;
|
58
|
+
}
|
59
|
+
return iter;
|
60
|
+
}
|
61
|
+
|
62
|
+
//---------------------------------------------------------------------------
|
63
|
+
string::const_iterator txp_find_par(
|
64
|
+
string::const_iterator begin,
|
65
|
+
string::const_iterator end,
|
66
|
+
VALUE tag
|
67
|
+
)
|
68
|
+
{
|
69
|
+
// TODO:
|
70
|
+
// Tenemos que hacer el mismo recorrido a partir de "begin" que en el
|
71
|
+
// bucle de parsing, pero esta vez sólo para encontrar un tag coincidente
|
72
|
+
// con el que nos pasan... Todo esto no es más que una prueba, habría que
|
73
|
+
// hacer un algoritmo más "robusto" para esto (Por ejemplo con pilas para
|
74
|
+
// encontrar un tag balanceado, ahora no pueden estar anidados.)
|
75
|
+
|
76
|
+
string::const_iterator old;
|
77
|
+
|
78
|
+
while (begin != end) {
|
79
|
+
begin = txp_find_tag(begin, end);
|
80
|
+
if (begin != end) {
|
81
|
+
// Estamos en un tag...
|
82
|
+
old = begin;
|
83
|
+
begin = txp_find_close(begin, end);
|
84
|
+
if (begin != end) {
|
85
|
+
VALUE tag_txt = rb_str_new2(string(old, begin).c_str());
|
86
|
+
VALUE new_tag = rb_class_new_instance(1, &tag_txt, rb_const_get(mTXParse, rb_intern("Tag")));
|
87
|
+
/*
|
88
|
+
printf(":::: SEARCHING PAR (D:'%s' vs '%s', N:'%s' vs. '%s')\n"
|
89
|
+
, RSTRING(rb_iv_get(tag, "@domain"))->ptr
|
90
|
+
, RSTRING(rb_iv_get(new_tag, "@domain"))->ptr
|
91
|
+
, RSTRING(rb_iv_get(tag, "@name"))->ptr
|
92
|
+
, RSTRING(rb_iv_get(new_tag, "@name"))->ptr
|
93
|
+
);
|
94
|
+
*/
|
95
|
+
|
96
|
+
// Vale, comprobamos que el tag se llama igual...
|
97
|
+
if (!rb_str_cmp(rb_iv_get(tag, "@domain"), rb_iv_get(new_tag, "@domain")) &&
|
98
|
+
!rb_str_cmp(rb_iv_get(tag, "@name"), rb_iv_get(new_tag, "@name"))) {
|
99
|
+
// printf(":::: FOUND!!!\n");
|
100
|
+
|
101
|
+
// Es el mismo TAG... ¿Es de cierre?
|
102
|
+
if (rb_iv_get(new_tag, "@is_close") == Qtrue) {
|
103
|
+
// printf(":::: New Tag is CLOSE\n");
|
104
|
+
// printf(":::: DBG: [%s]\n", string(old, end).c_str());
|
105
|
+
return old;
|
106
|
+
}
|
107
|
+
}
|
108
|
+
}
|
109
|
+
}
|
110
|
+
}
|
111
|
+
return end; // What else?
|
112
|
+
}
|
113
|
+
|
114
|
+
|
115
|
+
#define DEBUG_POS(str, pos) \
|
116
|
+
{\
|
117
|
+
string strdebug = string(str.size(), ' '); \
|
118
|
+
strdebug[pos] = '$'; \
|
119
|
+
printf("|%s|\n", str.c_str()); \
|
120
|
+
printf("|%s|\n", strdebug.c_str()); \
|
121
|
+
}
|
122
|
+
|
123
|
+
//---------------------------------------------------------------------------
|
124
|
+
void txp_parse_tag(const string tag, string &domain, string &name, map<string, string> &attrs, bool &close)
|
125
|
+
{
|
126
|
+
string::size_type pos = 0, pos2;
|
127
|
+
|
128
|
+
if ((tag.size() == 0) || (tag[pos++] != '<')) {
|
129
|
+
rb_raise(rb_eSyntaxError, "Tag should begin with '<'");
|
130
|
+
// rb_raise no retorna...
|
131
|
+
}
|
132
|
+
|
133
|
+
if (tag[pos] == '/') {
|
134
|
+
close = true;
|
135
|
+
pos++;
|
136
|
+
}
|
137
|
+
|
138
|
+
pos2 = tag.find_first_of(":/> \t\r\n", pos);
|
139
|
+
if ((pos2 == string::npos) || (tag[pos2] != ':')) {
|
140
|
+
rb_warn("TAG Should have a 'domain'. Assuming 'dmstk'");
|
141
|
+
// rb_raise(rb_eSyntaxError, "Tag should have a domain.");
|
142
|
+
domain = "dmstk";
|
143
|
+
name = string(tag, pos, pos2 - pos);
|
144
|
+
} else {
|
145
|
+
domain = string(tag, pos, pos2 - pos);
|
146
|
+
pos = pos2 + 1;
|
147
|
+
pos2 = tag.find_first_of(":/> \t\r\n", pos);
|
148
|
+
name = string(tag, pos, pos2 - pos);
|
149
|
+
}
|
150
|
+
|
151
|
+
// Si soy tag de cierre, no debo tener attributos.
|
152
|
+
if (close) return;
|
153
|
+
|
154
|
+
// Parseado el dominio y el nombre, saltamos a los attributos...
|
155
|
+
pos = tag.find_first_not_of(" \t\r\n", pos2);
|
156
|
+
if ((pos == string::npos) || (pos == '>')) return;
|
157
|
+
|
158
|
+
while ((pos != string::npos) && (tag[pos] != '>')) {
|
159
|
+
// Caso especial del tag de autocierre y el final de tag '>'
|
160
|
+
if ((tag[pos] == '/') && (tag[pos+1] == '>')) {
|
161
|
+
close = true; // autoclose ??
|
162
|
+
pos = string::npos;
|
163
|
+
break;
|
164
|
+
}
|
165
|
+
|
166
|
+
pos2 = tag.find_first_of(" \t\r\n,<>/=", pos);
|
167
|
+
string attrname = string(tag, pos, pos2 - pos);
|
168
|
+
string attrval = "";
|
169
|
+
|
170
|
+
pos2 = tag.find_first_not_of(" \t\r\n", pos2);
|
171
|
+
if ((pos2 != string::npos) && (tag[pos2]=='=')) {
|
172
|
+
// Parseando valor de atributo
|
173
|
+
pos2 = tag.find_first_not_of(" \t\r\n", pos2+1);
|
174
|
+
|
175
|
+
switch (tag[pos2]) {
|
176
|
+
case '\'': pos = pos2+1; pos2 = tag.find_first_of("'", pos); break;
|
177
|
+
case '"': pos = pos2+1; pos2 = tag.find_first_of("\"", pos); break;
|
178
|
+
default: pos = pos2; pos2 = tag.find_first_of(" \t\r\n"); break;
|
179
|
+
}
|
180
|
+
attrval = string(tag, pos, pos2 - pos);
|
181
|
+
} else {
|
182
|
+
// Atributo sin valores!! Asumimos --> nombre="nombre"
|
183
|
+
attrval = attrname;
|
184
|
+
}
|
185
|
+
|
186
|
+
attrs[attrname] = attrval;
|
187
|
+
|
188
|
+
// Tenemos que dejar "pos" en el siguiente atributo...
|
189
|
+
pos = tag.find_first_not_of(" \t\r\n", pos2+1);
|
190
|
+
}
|
191
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#ifndef TXPARSE_LIB
|
2
|
+
#define TXPARSE_LIB
|
3
|
+
|
4
|
+
#include <string>
|
5
|
+
#include <map>
|
6
|
+
|
7
|
+
using namespace std;
|
8
|
+
|
9
|
+
extern string txp_domain_str;
|
10
|
+
|
11
|
+
//---------------------------------------------------------------------------
|
12
|
+
string::const_iterator txp_find_tag(string::const_iterator iter, string::const_iterator end);
|
13
|
+
string::const_iterator txp_find_close(string::const_iterator iter, string::const_iterator end);
|
14
|
+
string::const_iterator txp_find_par(string::const_iterator begin, string::const_iterator end, VALUE tag);
|
15
|
+
void txp_parse_tag(const string tag, string &domain, string &name, map<string, string> &attrs, bool &close);
|
16
|
+
|
17
|
+
#endif
|
@@ -0,0 +1,109 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include "txparse.h"
|
3
|
+
|
4
|
+
extern "C" VALUE tag_initialize(VALUE self, VALUE orig)
|
5
|
+
{
|
6
|
+
string domain, name;
|
7
|
+
map<string, string> attrs;
|
8
|
+
bool is_close = false;
|
9
|
+
VALUE attr_hash = rb_hash_new();
|
10
|
+
|
11
|
+
rb_check_type(orig, T_STRING);
|
12
|
+
txp_parse_tag(string(RSTRING(orig)->ptr), domain, name, attrs, is_close);
|
13
|
+
|
14
|
+
/*
|
15
|
+
printf("PARSE-TAG DBG: ORIG='%s'\n", RSTRING(orig)->ptr);
|
16
|
+
printf(" DOMAIN='%s', NAME='%s'\n", domain.c_str(), name.c_str());
|
17
|
+
printf(" ATTRS(num)='%d', CLOSED='%c'\n", (int)attrs.size(), is_close ? 'Y' : 'N');
|
18
|
+
*/
|
19
|
+
|
20
|
+
if (attrs.size()) {
|
21
|
+
for (map<string, string>::const_iterator iter = attrs.begin()
|
22
|
+
; iter != attrs.end()
|
23
|
+
; ++iter)
|
24
|
+
{
|
25
|
+
rb_hash_aset(attr_hash, rb_str_new2((*iter).first.c_str()), rb_str_new2((*iter).second.c_str()));
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
rb_iv_set(self, "@name", rb_str_new2(name.c_str()));
|
30
|
+
rb_iv_set(self, "@domain", rb_str_new2(domain.c_str()));
|
31
|
+
rb_iv_set(self, "@is_close", is_close ? Qtrue : Qfalse);
|
32
|
+
rb_iv_set(self, "@attr", attr_hash);
|
33
|
+
rb_iv_set(self, "@orig", orig);
|
34
|
+
return self;
|
35
|
+
}
|
36
|
+
|
37
|
+
extern "C" VALUE tag_name(VALUE self)
|
38
|
+
{
|
39
|
+
return rb_iv_get(self, "@name");
|
40
|
+
}
|
41
|
+
|
42
|
+
extern "C" VALUE tag_name_set(VALUE self, VALUE new_name)
|
43
|
+
{
|
44
|
+
return rb_iv_set(self, "@name", new_name);
|
45
|
+
}
|
46
|
+
|
47
|
+
|
48
|
+
extern "C" VALUE tag_domain(VALUE self)
|
49
|
+
{
|
50
|
+
return rb_iv_get(self, "@domain");
|
51
|
+
}
|
52
|
+
|
53
|
+
extern "C" VALUE tag_domain_set(VALUE self, VALUE new_domain)
|
54
|
+
{
|
55
|
+
return rb_iv_set(self, "@domain", new_domain);
|
56
|
+
}
|
57
|
+
|
58
|
+
extern "C" VALUE tag_thing(VALUE self)
|
59
|
+
{
|
60
|
+
return rb_iv_get(self, "@thing");
|
61
|
+
}
|
62
|
+
|
63
|
+
extern "C" VALUE tag_thing_set(VALUE self, VALUE new_thing)
|
64
|
+
{
|
65
|
+
return rb_iv_set(self, "@thing", new_thing);
|
66
|
+
}
|
67
|
+
|
68
|
+
extern "C" VALUE tag_attributes(VALUE self)
|
69
|
+
{
|
70
|
+
return rb_iv_get(self, "@attr");
|
71
|
+
}
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
extern "C" VALUE tag_is_close(VALUE self)
|
76
|
+
{
|
77
|
+
return rb_iv_get(self, "@is_close");
|
78
|
+
}
|
79
|
+
|
80
|
+
extern "C" VALUE tag_orig(VALUE self)
|
81
|
+
{
|
82
|
+
return rb_iv_get(self, "@orig");
|
83
|
+
}
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
|
88
|
+
VALUE mTXParseTag = Qnil;
|
89
|
+
void Init_TXParseTag()
|
90
|
+
{
|
91
|
+
// VALUE TXParse_Module = rb_define_module("TXParse");
|
92
|
+
mTXParseTag = rb_define_class_under(mTXParse, "Tag", rb_cObject);
|
93
|
+
|
94
|
+
rb_define_method(mTXParseTag, "initialize", RUBY_METHOD_FUNC(tag_initialize), 1);
|
95
|
+
|
96
|
+
rb_define_method(mTXParseTag, "name", RUBY_METHOD_FUNC(tag_name), 0);
|
97
|
+
rb_define_method(mTXParseTag, "name=", RUBY_METHOD_FUNC(tag_name_set), 1);
|
98
|
+
|
99
|
+
rb_define_method(mTXParseTag, "domain", RUBY_METHOD_FUNC(tag_domain), 0);
|
100
|
+
rb_define_method(mTXParseTag, "domain=", RUBY_METHOD_FUNC(tag_domain_set), 1);
|
101
|
+
|
102
|
+
rb_define_method(mTXParseTag, "thing", RUBY_METHOD_FUNC(tag_thing), 0);
|
103
|
+
rb_define_method(mTXParseTag, "thing=", RUBY_METHOD_FUNC(tag_thing_set), 1);
|
104
|
+
|
105
|
+
rb_define_method(mTXParseTag, "attr", RUBY_METHOD_FUNC(tag_attributes), 0);
|
106
|
+
|
107
|
+
rb_define_method(mTXParseTag, "close?", RUBY_METHOD_FUNC(tag_is_close), 0);
|
108
|
+
rb_define_method(mTXParseTag, "orig", RUBY_METHOD_FUNC(tag_orig), 0);
|
109
|
+
}
|
data/lib/init_rails.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
begin
|
2
|
+
require File.join(File.dirname(__FILE__), 'txprails') # From here
|
3
|
+
rescue LoadError
|
4
|
+
begin
|
5
|
+
require 'txprails' # From gem
|
6
|
+
rescue LoadError => e
|
7
|
+
# gems:install may be run to install TXPRails with the skeleton plugin
|
8
|
+
# but not the gem itself installed.
|
9
|
+
# Don't die if this is the case.
|
10
|
+
raise e unless defined?(Rake) && Rake.application.top_level_tasks.include?('gems:install')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Load TXPRails.
|
15
|
+
# TXPRails may be undefined if we're running gems:install.
|
16
|
+
TXPRails.init_rails if defined?(TXPRails)
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module TXPRails
|
5
|
+
# This module handles miscelaneous command line utilities
|
6
|
+
class Commands
|
7
|
+
# @param args [Array<String>] The command-line arguments
|
8
|
+
def initialize(args)
|
9
|
+
@args = args
|
10
|
+
@options = {}
|
11
|
+
@options[:requires] = [] # ??
|
12
|
+
@options[:load_paths] = [] # ??
|
13
|
+
end
|
14
|
+
|
15
|
+
# Parses the command-line arguments and runs the executable.
|
16
|
+
# Calls `Kernel#exit` at the end, so it never returns.
|
17
|
+
def parse!
|
18
|
+
begin
|
19
|
+
@opts = OptionParser.new(&method(:set_opts))
|
20
|
+
@opts.parse!(@args)
|
21
|
+
@options
|
22
|
+
rescue Exception => e
|
23
|
+
raise e if e.is_a?(SystemExit)
|
24
|
+
|
25
|
+
$stderr.puts e.message
|
26
|
+
exit 1
|
27
|
+
end
|
28
|
+
exit 0
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [String] A description of the executable
|
32
|
+
def to_s
|
33
|
+
@opts.to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
# Tells optparse how to parse the arguments
|
39
|
+
# available for all executables.
|
40
|
+
#
|
41
|
+
# This is meant to be overridden by subclasses
|
42
|
+
# so they can add their own options.
|
43
|
+
#
|
44
|
+
# @param opts [OptionParser]
|
45
|
+
def set_opts(opts)
|
46
|
+
opts.on_tail("-?", "-h", "--help", "Show this message") do
|
47
|
+
puts opts
|
48
|
+
exit
|
49
|
+
end
|
50
|
+
|
51
|
+
opts.on_tail("-v", "--version", "Print version") do
|
52
|
+
puts("TXPRails #{::TXPRails.version[:string]}")
|
53
|
+
exit
|
54
|
+
end
|
55
|
+
|
56
|
+
opts.on('--rails RAILS_DIR', "Install TXPRails from the Gem to a Rails project") do |dir|
|
57
|
+
original_dir = dir
|
58
|
+
dir = File.join(dir, 'vendor', 'plugins')
|
59
|
+
unless File.exists?(dir)
|
60
|
+
puts "Directory #{dir} doesn't exist"
|
61
|
+
exit
|
62
|
+
end
|
63
|
+
|
64
|
+
dir = File.join(dir, 'txprails')
|
65
|
+
if File.exists?(dir)
|
66
|
+
print "Directory #{dir} already exists, overwrite [y/N]? "
|
67
|
+
exit if gets !~ /y/i
|
68
|
+
FileUtils.rm_rf(dir)
|
69
|
+
end
|
70
|
+
|
71
|
+
begin
|
72
|
+
Dir.mkdir(dir)
|
73
|
+
rescue SystemCallError
|
74
|
+
puts "Cannot create #{dir}"
|
75
|
+
exit
|
76
|
+
end
|
77
|
+
|
78
|
+
File.open(File.join(dir, 'init.rb'), 'w') do |file|
|
79
|
+
file << File.read(File.dirname(__FILE__) + "/../init_rails.rb")
|
80
|
+
end
|
81
|
+
|
82
|
+
puts "Haml plugin added to #{original_dir}"
|
83
|
+
exit
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Simple template initialization code
|
2
|
+
# Borrowed ideas from Haml, but VERY much simplyfied
|
3
|
+
# WARNING: We choose to use the plugin approach, so NO RAILS < 2.1.0 compatibility!
|
4
|
+
|
5
|
+
module TXPRails
|
6
|
+
|
7
|
+
class TXPTemplateHandler < TXPRails::Util.av_template_class(:Handler)
|
8
|
+
include TXP
|
9
|
+
|
10
|
+
def initialize(view)
|
11
|
+
@view = view
|
12
|
+
end
|
13
|
+
|
14
|
+
def render(template, local_assigns = {})
|
15
|
+
parse(template.source)
|
16
|
+
end
|
17
|
+
|
18
|
+
def compilable?
|
19
|
+
false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
if defined? ActionView::Template and ActionView::Template.respond_to? :register_template_handler
|
26
|
+
ActionView::Template
|
27
|
+
else
|
28
|
+
ActionView::Base
|
29
|
+
end.register_template_handler(:txp, TXPRails::TXPTemplateHandler)
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module TXPRails
|
2
|
+
# A module containing various useful functions.
|
3
|
+
module Util
|
4
|
+
extend self
|
5
|
+
|
6
|
+
# An array of ints representing the Ruby version number.
|
7
|
+
RUBY_VERSION = ::RUBY_VERSION.split(".").map {|s| s.to_i}
|
8
|
+
|
9
|
+
# Returns the path of a file relative to the Haml root directory.
|
10
|
+
#
|
11
|
+
# @param file [String] The filename relative to the Haml root
|
12
|
+
# @return [String] The filename relative to the the working directory
|
13
|
+
def scope(file)
|
14
|
+
File.join(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__)))), file)
|
15
|
+
end
|
16
|
+
|
17
|
+
## Cross Rails Version Compatibility
|
18
|
+
|
19
|
+
# Returns the root of the Rails application,
|
20
|
+
# if this is running in a Rails context.
|
21
|
+
# Returns `nil` if no such root is defined.
|
22
|
+
#
|
23
|
+
# @return [String, nil]
|
24
|
+
def rails_root
|
25
|
+
return Rails.root.to_s if defined?(Rails.root)
|
26
|
+
return RAILS_ROOT.to_s if defined?(RAILS_ROOT)
|
27
|
+
return nil
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns an ActionView::Template* class.
|
31
|
+
# In pre-3.0 versions of Rails, most of these classes
|
32
|
+
# were of the form `ActionView::TemplateFoo`,
|
33
|
+
# while afterwards they were of the form `ActionView::Template::Foo`.
|
34
|
+
#
|
35
|
+
# @param name [#to_s] The name of the class to get.
|
36
|
+
# For example, `:Error` will return `ActionView::TemplateError`
|
37
|
+
# or `ActionView::Template::Error`.
|
38
|
+
def av_template_class(name)
|
39
|
+
return ActionView.const_get("Template#{name}") if ActionView.const_defined?("Template#{name}")
|
40
|
+
return ActionView::Template.const_get(name.to_s)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'txprails/util'
|
2
|
+
|
3
|
+
module TXPRails
|
4
|
+
# Handles TXPRails version-reporting.
|
5
|
+
# TXPRails not only reports the standard three version numbers,
|
6
|
+
# but its Git revision hash as well,
|
7
|
+
# if it was installed from Git.
|
8
|
+
module Version
|
9
|
+
include TXPRails::Util
|
10
|
+
|
11
|
+
# Returns a hash representing the version of TXPRails.
|
12
|
+
# The `:major`, `:minor`, and `:teeny` keys have their respective numbers as Fixnums.
|
13
|
+
# The `:name` key has the name of the version.
|
14
|
+
# The `:string` key contains a human-readable string representation of the version.
|
15
|
+
# The `:number` key is the major, minor, and teeny keys separated by periods.
|
16
|
+
# If TXPRails is checked out from Git, the `:rev` key will have the revision hash.
|
17
|
+
# For example:
|
18
|
+
#
|
19
|
+
# {
|
20
|
+
# :string => "2.1.0.9616393",
|
21
|
+
# :rev => "9616393b8924ef36639c7e82aa88a51a24d16949",
|
22
|
+
# :number => "2.1.0",
|
23
|
+
# :major => 2, :minor => 1, :teeny => 0
|
24
|
+
# }
|
25
|
+
#
|
26
|
+
# @return [{Symbol => String/Fixnum}] The version hash
|
27
|
+
def version
|
28
|
+
return @@version if defined?(@@version)
|
29
|
+
|
30
|
+
numbers = File.read(scope('VERSION')).strip.split('.').map { |n| n.to_i }
|
31
|
+
name = File.read(scope('VERSION_NAME')).strip
|
32
|
+
@@version = {
|
33
|
+
:major => numbers[0],
|
34
|
+
:minor => numbers[1],
|
35
|
+
:teeny => numbers[2],
|
36
|
+
:name => name
|
37
|
+
}
|
38
|
+
@@version[:number] = [:major, :minor, :teeny].map { |comp| @@version[comp] }.compact.join('.')
|
39
|
+
@@version[:string] = @@version[:number].dup
|
40
|
+
|
41
|
+
if File.exists?(scope('REVISION'))
|
42
|
+
rev = File.read(scope('REVISION')).strip
|
43
|
+
rev = nil if rev !~ /^([a-f0-9]+|\(.*\))$/
|
44
|
+
end
|
45
|
+
|
46
|
+
if (rev.nil? || rev == '(unknown)') && File.exists?(scope('.git/HEAD'))
|
47
|
+
rev = File.read(scope('.git/HEAD')).strip
|
48
|
+
if rev =~ /^ref: (.*)$/
|
49
|
+
rev = File.read(scope(".git/#{$1}")).strip
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
if rev
|
54
|
+
@@version[:rev] = rev
|
55
|
+
unless rev[0] == ?(
|
56
|
+
@@version[:string] << "." << rev[0...7]
|
57
|
+
end
|
58
|
+
@@version[:string] << " (#{name})"
|
59
|
+
end
|
60
|
+
|
61
|
+
@@version
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/txprails.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'txprails/txparse'
|
2
|
+
require 'txprails/version'
|
3
|
+
|
4
|
+
module TXPRails
|
5
|
+
extend TXPRails::Version
|
6
|
+
|
7
|
+
# A string representing the version of TXPRails.
|
8
|
+
# A more fine-grained representation is available from TXPRails.version.
|
9
|
+
VERSION = version[:string] unless defined?(TXPRails::VERSION)
|
10
|
+
|
11
|
+
# Initializes TXPRails for Rails.
|
12
|
+
#
|
13
|
+
# This method is called by `init.rb`,
|
14
|
+
# which is run by Rails on startup.
|
15
|
+
# We use it rather than putting stuff straight into `init.rb`
|
16
|
+
# so we can change the initialization behavior
|
17
|
+
# without modifying the file itself.
|
18
|
+
#
|
19
|
+
def self.init_rails
|
20
|
+
%w[txprails/template].each {|f| require f}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
require 'txprails/util'
|
25
|
+
|
26
|
+
module TXP
|
27
|
+
include TXParse
|
28
|
+
|
29
|
+
def txp_doc(tag)
|
30
|
+
"<!DOCTYPE html>"
|
31
|
+
end
|
32
|
+
|
33
|
+
def txp_content(tag)
|
34
|
+
if content_for_layout = @view.instance_variable_get("@content_for_layout")
|
35
|
+
parse(content_for_layout)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def txp_include(tag)
|
40
|
+
@view.render :partial => tag.attr["name"]
|
41
|
+
end
|
42
|
+
|
43
|
+
# self.extend self
|
44
|
+
end
|
data/test/helper.rb
ADDED