mirror of
https://github.com/kemko/liquid.git
synced 2026-01-02 00:05:42 +03:00
Compare commits
4 Commits
ragel_c
...
hotfix_bla
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9559d69e11 | ||
|
|
50bd34fd78 | ||
|
|
ee41b3f4a3 | ||
|
|
05d9976e16 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -4,5 +4,3 @@
|
||||
pkg
|
||||
*.rbc
|
||||
.rvmrc
|
||||
*.o
|
||||
*.bundle
|
||||
|
||||
44
Rakefile
44
Rakefile
@@ -2,50 +2,12 @@
|
||||
|
||||
require 'rubygems'
|
||||
require 'rake'
|
||||
require 'rake/clean'
|
||||
require 'fileutils'
|
||||
require 'rake/testtask'
|
||||
require 'rubygems/package_task'
|
||||
|
||||
task :default => [:compile, :test]
|
||||
task :default => 'test'
|
||||
|
||||
task :ragel do
|
||||
sh "find . -name '*.rl' | xargs ragel -C -G2"
|
||||
end
|
||||
|
||||
task :compile => [:ragel, :liquid_ext]
|
||||
|
||||
extension = "liquid_ext"
|
||||
ext = "ext/liquid"
|
||||
ext_so = "#{ext}/#{extension}.#{RbConfig::CONFIG['DLEXT']}"
|
||||
ext_files = FileList[
|
||||
"#{ext}/*.c",
|
||||
"#{ext}/*.h",
|
||||
"#{ext}/*.rl",
|
||||
"#{ext}/extconf.rb",
|
||||
"#{ext}/Makefile",
|
||||
"lib"
|
||||
]
|
||||
|
||||
task "lib" do
|
||||
directory "lib"
|
||||
end
|
||||
|
||||
desc "Builds just the #{extension} extension"
|
||||
task extension.to_sym => [:ragel, "#{ext}/Makefile", ext_so ]
|
||||
|
||||
file "#{ext}/Makefile" => ["#{ext}/extconf.rb"] do
|
||||
Dir.chdir(ext) do ruby "extconf.rb" end
|
||||
end
|
||||
|
||||
file ext_so => ext_files do
|
||||
Dir.chdir(ext) do
|
||||
sh "make"
|
||||
end
|
||||
cp ext_so, "lib"
|
||||
end
|
||||
|
||||
Rake::TestTask.new(:test => [:ragel, 'liquid_ext']) do |t|
|
||||
Rake::TestTask.new(:test) do |t|
|
||||
t.libs << '.' << 'lib' << 'test'
|
||||
t.test_files = FileList['test/liquid/**/*_test.rb']
|
||||
t.verbose = false
|
||||
@@ -80,7 +42,7 @@ namespace :profile do
|
||||
|
||||
desc "Run KCacheGrind"
|
||||
task :grind => :run do
|
||||
system "qcachegrind /tmp//callgrind.liquid.txt"
|
||||
system "qcachegrind /tmp/liquid.rubyprof_calltreeprinter.txt"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,213 +0,0 @@
|
||||
|
||||
SHELL = /bin/sh
|
||||
|
||||
# V=0 quiet, V=1 verbose. other values don't work.
|
||||
V = 0
|
||||
Q1 = $(V:1=)
|
||||
Q = $(Q1:0=@)
|
||||
n=$(NULLCMD)
|
||||
ECHO1 = $(V:1=@$n)
|
||||
ECHO = $(ECHO1:0=@echo)
|
||||
|
||||
#### Start of system configuration section. ####
|
||||
|
||||
srcdir = .
|
||||
topdir = /Users/tobi/.rbenv/versions/1.9.3-p194-perf/include/ruby-1.9.1
|
||||
hdrdir = /Users/tobi/.rbenv/versions/1.9.3-p194-perf/include/ruby-1.9.1
|
||||
arch_hdrdir = /Users/tobi/.rbenv/versions/1.9.3-p194-perf/include/ruby-1.9.1/$(arch)
|
||||
VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby
|
||||
prefix = $(DESTDIR)/Users/tobi/.rbenv/versions/1.9.3-p194-perf
|
||||
exec_prefix = $(prefix)
|
||||
rubylibprefix = $(libdir)/$(RUBY_BASE_NAME)
|
||||
bindir = $(exec_prefix)/bin
|
||||
sbindir = $(exec_prefix)/sbin
|
||||
libexecdir = $(exec_prefix)/libexec
|
||||
datarootdir = $(prefix)/share
|
||||
datadir = $(datarootdir)
|
||||
sysconfdir = $(prefix)/etc
|
||||
sharedstatedir = $(prefix)/com
|
||||
localstatedir = $(prefix)/var
|
||||
includedir = $(prefix)/include
|
||||
oldincludedir = $(DESTDIR)/usr/include
|
||||
docdir = $(datarootdir)/doc/$(PACKAGE)
|
||||
infodir = $(datarootdir)/info
|
||||
htmldir = $(docdir)
|
||||
dvidir = $(docdir)
|
||||
pdfdir = $(docdir)
|
||||
psdir = $(docdir)
|
||||
libdir = $(exec_prefix)/lib
|
||||
localedir = $(datarootdir)/locale
|
||||
mandir = $(datarootdir)/man
|
||||
ridir = $(datarootdir)/$(RI_BASE_NAME)
|
||||
sitedir = $(rubylibprefix)/site_ruby
|
||||
vendordir = $(rubylibprefix)/vendor_ruby
|
||||
rubyhdrdir = $(includedir)/$(RUBY_BASE_NAME)-$(ruby_version)
|
||||
sitehdrdir = $(rubyhdrdir)/site_ruby
|
||||
vendorhdrdir = $(rubyhdrdir)/vendor_ruby
|
||||
rubylibdir = $(rubylibprefix)/$(ruby_version)
|
||||
archdir = $(rubylibdir)/$(arch)
|
||||
sitelibdir = $(sitedir)/$(ruby_version)
|
||||
sitearchdir = $(sitelibdir)/$(sitearch)
|
||||
vendorlibdir = $(vendordir)/$(ruby_version)
|
||||
vendorarchdir = $(vendorlibdir)/$(sitearch)
|
||||
|
||||
NULLCMD = :
|
||||
|
||||
CC = /usr/bin/gcc-4.2
|
||||
CXX = g++
|
||||
LIBRUBY = $(LIBRUBY_A)
|
||||
LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
|
||||
LIBRUBYARG_SHARED =
|
||||
LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
|
||||
OUTFLAG = -o
|
||||
COUTFLAG = -o
|
||||
|
||||
RUBY_EXTCONF_H =
|
||||
cflags = $(optflags) $(debugflags) $(warnflags)
|
||||
optflags = -O3
|
||||
debugflags = -ggdb
|
||||
warnflags = -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wshorten-64-to-32 -Wimplicit-function-declaration
|
||||
CFLAGS = -fno-common $(cflags) -pipe $(ARCH_FLAG)
|
||||
INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir)
|
||||
DEFS =
|
||||
CPPFLAGS = -I'/Users/tobi/.rbenv/versions/1.9.3-p194-perf/include' -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE $(DEFS) $(cppflags)
|
||||
CXXFLAGS = $(CFLAGS) $(cxxflags)
|
||||
ldflags = -L. -L'/Users/tobi/.rbenv/versions/1.9.3-p194-perf/lib' -L/usr/local/lib
|
||||
dldflags = -Wl,-undefined,dynamic_lookup -Wl,-multiply_defined,suppress -Wl,-flat_namespace
|
||||
ARCH_FLAG =
|
||||
DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG)
|
||||
LDSHARED = $(CC) -dynamic -bundle
|
||||
LDSHAREDXX = $(CXX) -dynamic -bundle
|
||||
AR = ar
|
||||
EXEEXT =
|
||||
|
||||
RUBY_BASE_NAME = ruby
|
||||
RUBY_INSTALL_NAME = ruby
|
||||
RUBY_SO_NAME = ruby
|
||||
arch = x86_64-darwin12.0.0
|
||||
sitearch = $(arch)
|
||||
ruby_version = 1.9.1
|
||||
ruby = /Users/tobi/.rbenv/versions/1.9.3-p194-perf/bin/ruby
|
||||
RUBY = $(ruby)
|
||||
RM = rm -f
|
||||
RM_RF = $(RUBY) -run -e rm -- -rf
|
||||
RMDIRS = rmdir -p
|
||||
MAKEDIRS = mkdir -p
|
||||
INSTALL = /usr/bin/install -c
|
||||
INSTALL_PROG = $(INSTALL) -m 0755
|
||||
INSTALL_DATA = $(INSTALL) -m 644
|
||||
COPY = cp
|
||||
|
||||
#### End of system configuration section. ####
|
||||
|
||||
preload =
|
||||
|
||||
libpath = . $(libdir)
|
||||
LIBPATH = -L. -L$(libdir)
|
||||
DEFFILE =
|
||||
|
||||
CLEANFILES = mkmf.log
|
||||
DISTCLEANFILES =
|
||||
DISTCLEANDIRS =
|
||||
|
||||
extout =
|
||||
extout_prefix =
|
||||
target_prefix =
|
||||
LOCAL_LIBS =
|
||||
LIBS = -lc -lpthread -ldl -lobjc
|
||||
SRCS = liquid_ext.c
|
||||
OBJS = liquid_ext.o
|
||||
TARGET = liquid_ext
|
||||
DLLIB = $(TARGET).bundle
|
||||
EXTSTATIC =
|
||||
STATIC_LIB =
|
||||
|
||||
BINDIR = $(bindir)
|
||||
RUBYCOMMONDIR = $(sitedir)$(target_prefix)
|
||||
RUBYLIBDIR = $(sitelibdir)$(target_prefix)
|
||||
RUBYARCHDIR = $(sitearchdir)$(target_prefix)
|
||||
HDRDIR = $(rubyhdrdir)/ruby$(target_prefix)
|
||||
ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix)
|
||||
|
||||
TARGET_SO = $(DLLIB)
|
||||
CLEANLIBS = $(TARGET).bundle
|
||||
CLEANOBJS = *.o *.bak
|
||||
|
||||
all: $(DLLIB)
|
||||
static: $(STATIC_LIB)
|
||||
.PHONY: all install static install-so install-rb
|
||||
.PHONY: clean clean-so clean-rb
|
||||
|
||||
clean-rb-default::
|
||||
clean-rb::
|
||||
clean-so::
|
||||
clean: clean-so clean-rb-default clean-rb
|
||||
@-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
|
||||
|
||||
distclean-rb-default::
|
||||
distclean-rb::
|
||||
distclean-so::
|
||||
distclean: clean distclean-so distclean-rb-default distclean-rb
|
||||
@-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
|
||||
@-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
|
||||
@-$(RMDIRS) $(DISTCLEANDIRS) 2> /dev/null || true
|
||||
|
||||
realclean: distclean
|
||||
install: install-so install-rb
|
||||
|
||||
install-so: $(RUBYARCHDIR)
|
||||
install-so: $(RUBYARCHDIR)/$(DLLIB)
|
||||
$(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
|
||||
@-$(MAKEDIRS) $(@D)
|
||||
$(INSTALL_PROG) $(DLLIB) $(@D)
|
||||
install-rb: pre-install-rb install-rb-default
|
||||
install-rb-default: pre-install-rb-default
|
||||
pre-install-rb: Makefile
|
||||
pre-install-rb-default: Makefile
|
||||
pre-install-rb-default:
|
||||
$(ECHO) installing default liquid_ext libraries
|
||||
$(RUBYARCHDIR):
|
||||
$(Q) $(MAKEDIRS) $@
|
||||
|
||||
site-install: site-install-so site-install-rb
|
||||
site-install-so: install-so
|
||||
site-install-rb: install-rb
|
||||
|
||||
.SUFFIXES: .c .m .cc .mm .cxx .cpp .C .o
|
||||
|
||||
.cc.o:
|
||||
$(ECHO) compiling $(<)
|
||||
$(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
||||
|
||||
.mm.o:
|
||||
$(ECHO) compiling $(<)
|
||||
$(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
||||
|
||||
.cxx.o:
|
||||
$(ECHO) compiling $(<)
|
||||
$(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
||||
|
||||
.cpp.o:
|
||||
$(ECHO) compiling $(<)
|
||||
$(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
||||
|
||||
.C.o:
|
||||
$(ECHO) compiling $(<)
|
||||
$(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
||||
|
||||
.c.o:
|
||||
$(ECHO) compiling $(<)
|
||||
$(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<
|
||||
|
||||
.m.o:
|
||||
$(ECHO) compiling $(<)
|
||||
$(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<
|
||||
|
||||
$(DLLIB): $(OBJS) Makefile
|
||||
$(ECHO) linking shared-object $(DLLIB)
|
||||
@-$(RM) $(@)
|
||||
$(Q) $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
|
||||
|
||||
|
||||
|
||||
$(OBJS): $(hdrdir)/ruby.h $(hdrdir)/ruby/defines.h $(arch_hdrdir)/ruby/config.h
|
||||
@@ -1,6 +0,0 @@
|
||||
require 'mkmf'
|
||||
|
||||
dir_config("liquid_ext")
|
||||
have_library("c", "main")
|
||||
|
||||
create_makefile("liquid_ext")
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -1,159 +0,0 @@
|
||||
/*
|
||||
Parser for context#[] method. Generated through ragel from parser.rl
|
||||
Only modify parser.rl. Run rake ragel afterwards to generate this file.
|
||||
*/
|
||||
|
||||
#include <ruby.h>
|
||||
|
||||
%%{
|
||||
machine fsm;
|
||||
|
||||
action mark {
|
||||
mark = p;
|
||||
}
|
||||
|
||||
action lookup {
|
||||
EMIT("lookup", Qnil)
|
||||
}
|
||||
|
||||
action call {
|
||||
EMIT("call", Qnil)
|
||||
}
|
||||
action range {
|
||||
EMIT("range", Qnil)
|
||||
}
|
||||
|
||||
constants = ( "true" | "false" | "nil" | "null" );
|
||||
|
||||
# strings
|
||||
string = "\"" any* "\"" | "'" any* "'";
|
||||
|
||||
# nothingness
|
||||
nil = "nil" | "null" ;
|
||||
|
||||
# numbers
|
||||
integer = ('+'|'-')? digit+;
|
||||
float = ('+'|'-')? digit+ '.' digit+;
|
||||
|
||||
# simple values
|
||||
primitive = (
|
||||
|
||||
integer >mark %{
|
||||
EMIT("id", rb_funcall(rb_cObject, rb_intern("Integer"), 1, rb_str_new(mark, p - mark)));
|
||||
} |
|
||||
|
||||
float >mark %{
|
||||
EMIT("id", rb_funcall(rb_cObject, rb_intern("Float"), 1, rb_str_new(mark, p - mark)))
|
||||
} |
|
||||
|
||||
nil %{ EMIT("id", Qnil) } |
|
||||
"true" %{ EMIT("id", Qtrue) } |
|
||||
"false" %{ EMIT("id", Qfalse) } |
|
||||
|
||||
string >mark %{ EMIT("id", rb_str_new(mark + 1, p - mark - 2)) }
|
||||
|
||||
);
|
||||
|
||||
entity = (
|
||||
((alpha [A-Za-z0-9_\-]*) - (constants)) >mark %{
|
||||
EMIT("id", rb_str_new(mark, p - mark))
|
||||
EMIT("lookup", Qnil)
|
||||
}
|
||||
);
|
||||
|
||||
# Because of recursion we cannot immediatly resolve the content of this in
|
||||
# the current grammar. We simply re-invoke the parser here to descend into
|
||||
# the substring
|
||||
recur = (
|
||||
(any+ - ']') >mark %{
|
||||
VALUE body = rb_str_new(mark, p - mark);
|
||||
liquid_context_parse_impl(body, tokens);
|
||||
}
|
||||
);
|
||||
|
||||
expr = (
|
||||
entity |
|
||||
primitive |
|
||||
"(" (primitive | entity) ".." (primitive | entity) <: ")" %range |
|
||||
"[" recur "]" %lookup
|
||||
);
|
||||
|
||||
hash_accessors = (
|
||||
"[" recur "]" %call |
|
||||
|
||||
".first" %{
|
||||
EMIT("buildin", rb_str_new2("first"))
|
||||
} |
|
||||
|
||||
".last" %{
|
||||
EMIT("buildin", rb_str_new2("last"))
|
||||
} |
|
||||
|
||||
".size" %{
|
||||
EMIT("buildin", rb_str_new2("size"))
|
||||
} |
|
||||
|
||||
"." ((alpha [A-Za-z0-9_\-]*) - ("first"|"last"|"size")) >mark %{
|
||||
EMIT("id", rb_str_new(mark, p - mark))
|
||||
EMIT("call", Qnil)
|
||||
}
|
||||
);
|
||||
|
||||
main := (
|
||||
|
||||
expr <: (hash_accessors)*
|
||||
|
||||
);
|
||||
|
||||
}%%
|
||||
|
||||
%% write data nofinal;
|
||||
|
||||
// def self.emit(sym, data, tokens)
|
||||
// puts "emitting: #{sym} -> #{data.inspect}" if $VERBOSE
|
||||
// tokens.push [sym, data]
|
||||
// end
|
||||
|
||||
#define EMIT(sym, data) rb_ary_push(tokens, rb_ary_new3(2, ID2SYM(rb_intern(sym)), data));
|
||||
|
||||
|
||||
void liquid_context_parse_impl(VALUE text, VALUE tokens)
|
||||
{
|
||||
char *p;
|
||||
char *pe;
|
||||
char *eof;
|
||||
char *mark;
|
||||
int cs, res = 0;
|
||||
|
||||
if (RSTRING_LEN(text) <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
mark = p = RSTRING_PTR(text);
|
||||
eof = pe = RSTRING_PTR(text) + RSTRING_LEN(text);
|
||||
|
||||
%% write init;
|
||||
%% write exec;
|
||||
}
|
||||
|
||||
VALUE liquid_context_parse(VALUE self, VALUE text) {
|
||||
VALUE tokens;
|
||||
|
||||
//printf("text: %s\n", RSTRING_PTR(text));
|
||||
|
||||
//Check_Type(text, T_STRING);
|
||||
|
||||
tokens = rb_ary_new();
|
||||
liquid_context_parse_impl(text, tokens);
|
||||
return tokens;
|
||||
}
|
||||
|
||||
static VALUE rb_Liquid;
|
||||
static VALUE rb_Parser;
|
||||
|
||||
void Init_liquid_ext()
|
||||
{
|
||||
rb_Liquid = rb_define_module("Liquid");
|
||||
rb_Parser = rb_define_class_under(rb_Liquid, "Parser", rb_cObject);
|
||||
rb_define_singleton_method(rb_Parser, "parse", liquid_context_parse, 1);
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
have_library: checking for main() in -lc... -------------------- yes
|
||||
|
||||
"/usr/bin/gcc-4.2 -o conftest -I/Users/tobi/.rbenv/versions/1.9.3-p194-perf/include/ruby-1.9.1/x86_64-darwin12.0.0 -I/Users/tobi/.rbenv/versions/1.9.3-p194-perf/include/ruby-1.9.1/ruby/backward -I/Users/tobi/.rbenv/versions/1.9.3-p194-perf/include/ruby-1.9.1 -I. -I'/Users/tobi/.rbenv/versions/1.9.3-p194-perf/include' -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -I'/Users/tobi/.rbenv/versions/1.9.3-p194-perf/include' -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wshorten-64-to-32 -Wimplicit-function-declaration -pipe conftest.c -L. -L/Users/tobi/.rbenv/versions/1.9.3-p194-perf/lib -L. -L'/Users/tobi/.rbenv/versions/1.9.3-p194-perf/lib' -L/usr/local/lib -lruby-static -lpthread -ldl -lobjc "
|
||||
checked program was:
|
||||
/* begin */
|
||||
1: #include "ruby.h"
|
||||
2:
|
||||
3: int main() {return 0;}
|
||||
/* end */
|
||||
|
||||
"/usr/bin/gcc-4.2 -o conftest -I/Users/tobi/.rbenv/versions/1.9.3-p194-perf/include/ruby-1.9.1/x86_64-darwin12.0.0 -I/Users/tobi/.rbenv/versions/1.9.3-p194-perf/include/ruby-1.9.1/ruby/backward -I/Users/tobi/.rbenv/versions/1.9.3-p194-perf/include/ruby-1.9.1 -I. -I'/Users/tobi/.rbenv/versions/1.9.3-p194-perf/include' -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -I'/Users/tobi/.rbenv/versions/1.9.3-p194-perf/include' -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wshorten-64-to-32 -Wimplicit-function-declaration -pipe conftest.c -L. -L/Users/tobi/.rbenv/versions/1.9.3-p194-perf/lib -L. -L'/Users/tobi/.rbenv/versions/1.9.3-p194-perf/lib' -L/usr/local/lib -lruby-static -lc -lpthread -ldl -lobjc "
|
||||
checked program was:
|
||||
/* begin */
|
||||
1: #include "ruby.h"
|
||||
2:
|
||||
3: /*top*/
|
||||
4: int main() {return 0;}
|
||||
5: int t() { void ((*volatile p)()); p = (void ((*)()))main; return 0; }
|
||||
/* end */
|
||||
|
||||
--------------------
|
||||
|
||||
@@ -62,7 +62,6 @@ require 'liquid/standardfilters'
|
||||
require 'liquid/condition'
|
||||
require 'liquid/module_ex'
|
||||
require 'liquid/utils'
|
||||
require 'liquid_ext'
|
||||
|
||||
# Load all the tags of the standard library
|
||||
#
|
||||
|
||||
@@ -109,7 +109,7 @@ module Liquid
|
||||
end
|
||||
end
|
||||
|
||||
output
|
||||
output.join
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
module Liquid
|
||||
|
||||
|
||||
# Context keeps the variable stack and resolves variables, as well as keywords
|
||||
#
|
||||
# context['variable'] = 'testing'
|
||||
@@ -115,89 +114,54 @@ module Liquid
|
||||
@scopes[0] = {}
|
||||
end
|
||||
|
||||
|
||||
# Look up variable, either resolve directly after considering the name. We can directly handle
|
||||
# Strings, digits, floats and booleans (true,false).
|
||||
# If no match is made we lookup the variable in the current scope and
|
||||
# later move up to the parent blocks to see if we can resolve the variable somewhere up the tree.
|
||||
# Some special keywords return symbols. Those symbols are to be called on the rhs object in expressions
|
||||
#
|
||||
# Example:
|
||||
# products == empty #=> products.empty?
|
||||
def resolve(key)
|
||||
case key
|
||||
when nil, ""
|
||||
return nil
|
||||
when "blank"
|
||||
return :blank?
|
||||
when "empty"
|
||||
return :empty?
|
||||
end
|
||||
|
||||
result = Parser.parse(key)
|
||||
stack = []
|
||||
|
||||
result.each do |(sym, value)|
|
||||
|
||||
case sym
|
||||
when :id
|
||||
stack.push value
|
||||
when :lookup
|
||||
left = stack.pop
|
||||
value = find_variable(left)
|
||||
|
||||
stack.push(harden(value))
|
||||
when :range
|
||||
right = stack.pop.to_i
|
||||
left = stack.pop.to_i
|
||||
|
||||
stack.push (left..right)
|
||||
when :buildin
|
||||
left = stack.pop
|
||||
value = invoke_buildin(left, value)
|
||||
|
||||
stack.push(harden(value))
|
||||
when :call
|
||||
left = stack.pop
|
||||
right = stack.pop
|
||||
value = lookup_and_evaluate(right, left)
|
||||
|
||||
stack.push(harden(value))
|
||||
else
|
||||
raise "unknown #{sym}"
|
||||
end
|
||||
end
|
||||
|
||||
return stack.first
|
||||
end
|
||||
|
||||
|
||||
# Only allow String, Numeric, Hash, Array, Proc, Boolean or <tt>Liquid::Drop</tt>
|
||||
def []=(key, value)
|
||||
@scopes[0][key] = value
|
||||
end
|
||||
|
||||
def [](key)
|
||||
resolve(key)
|
||||
end
|
||||
|
||||
def has_key?(key)
|
||||
resolve(key) != nil
|
||||
end
|
||||
|
||||
alias_method :[], :resolve
|
||||
|
||||
private
|
||||
LITERALS = {
|
||||
nil => nil, 'nil' => nil, 'null' => nil, '' => nil,
|
||||
'true' => true,
|
||||
'false' => false,
|
||||
'blank' => :blank?,
|
||||
'empty' => :empty?
|
||||
}
|
||||
|
||||
def invoke_buildin(obj, key)
|
||||
# as weird as this is, liquid unit tests demand that we prioritize hash lookups
|
||||
# to buildins. So if we got a hash and it has a :first element we need to call that
|
||||
# instead of sending the first message...
|
||||
|
||||
if obj.respond_to?(:has_key?) && obj.has_key?(key)
|
||||
return lookup_and_evaluate(obj, key)
|
||||
end
|
||||
|
||||
if obj.respond_to?(key)
|
||||
return obj.send(key)
|
||||
# Look up variable, either resolve directly after considering the name. We can directly handle
|
||||
# Strings, digits, floats and booleans (true,false).
|
||||
# If no match is made we lookup the variable in the current scope and
|
||||
# later move up to the parent blocks to see if we can resolve the variable somewhere up the tree.
|
||||
# Some special keywords return symbols. Those symbols are to be called on the rhs object in expressions
|
||||
#
|
||||
# Example:
|
||||
# products == empty #=> products.empty?
|
||||
def resolve(key)
|
||||
if LITERALS.key?(key)
|
||||
LITERALS[key]
|
||||
else
|
||||
return nil
|
||||
case key
|
||||
when /^'(.*)'$/ # Single quoted strings
|
||||
$1
|
||||
when /^"(.*)"$/ # Double quoted strings
|
||||
$1
|
||||
when /^(-?\d+)$/ # Integer and floats
|
||||
$1.to_i
|
||||
when /^\((\S+)\.\.(\S+)\)$/ # Ranges
|
||||
(resolve($1).to_i..resolve($2).to_i)
|
||||
when /^(-?\d[\d\.]+)$/ # Floats
|
||||
$1.to_f
|
||||
else
|
||||
variable(key)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -217,34 +181,71 @@ module Liquid
|
||||
scope ||= @environments.last || @scopes.last
|
||||
variable ||= lookup_and_evaluate(scope, key)
|
||||
|
||||
variable = variable.to_liquid
|
||||
variable.context = self if variable.respond_to?(:context=)
|
||||
|
||||
return variable
|
||||
end
|
||||
|
||||
# Resolves namespaced queries gracefully.
|
||||
#
|
||||
# Example
|
||||
# @context['hash'] = {"name" => 'tobi'}
|
||||
# assert_equal 'tobi', @context['hash.name']
|
||||
# assert_equal 'tobi', @context['hash["name"]']
|
||||
def variable(markup)
|
||||
parts = markup.scan(VariableParser)
|
||||
square_bracketed = /^\[(.*)\]$/
|
||||
|
||||
first_part = parts.shift
|
||||
|
||||
if first_part =~ square_bracketed
|
||||
first_part = resolve($1)
|
||||
end
|
||||
|
||||
if object = find_variable(first_part)
|
||||
|
||||
parts.each do |part|
|
||||
part = resolve($1) if part_resolved = (part =~ square_bracketed)
|
||||
|
||||
# If object is a hash- or array-like object we look for the
|
||||
# presence of the key and if its available we return it
|
||||
if object.respond_to?(:[]) and
|
||||
((object.respond_to?(:has_key?) and object.has_key?(part)) or
|
||||
(object.respond_to?(:fetch) and part.is_a?(Integer)))
|
||||
|
||||
# if its a proc we will replace the entry with the proc
|
||||
res = lookup_and_evaluate(object, part)
|
||||
object = res.to_liquid
|
||||
|
||||
# Some special cases. If the part wasn't in square brackets and
|
||||
# no key with the same name was found we interpret following calls
|
||||
# as commands and call them on the current object
|
||||
elsif !part_resolved and object.respond_to?(part) and ['size', 'first', 'last'].include?(part)
|
||||
|
||||
object = object.send(part.intern).to_liquid
|
||||
|
||||
# No key was present with the desired value and it wasn't one of the directly supported
|
||||
# keywords either. The only thing we got left is to return nil
|
||||
else
|
||||
return nil
|
||||
end
|
||||
|
||||
# If we are dealing with a drop here we have to
|
||||
object.context = self if object.respond_to?(:context=)
|
||||
end
|
||||
end
|
||||
|
||||
object
|
||||
end # variable
|
||||
|
||||
def lookup_and_evaluate(obj, key)
|
||||
return nil unless obj.respond_to?(:[])
|
||||
|
||||
if obj.is_a?(Array)
|
||||
return nil unless key.is_a?(Integer)
|
||||
if (value = obj[key]).is_a?(Proc) && obj.respond_to?(:[]=)
|
||||
obj[key] = (value.arity == 0) ? value.call : value.call(self)
|
||||
else
|
||||
value
|
||||
end
|
||||
|
||||
value = obj[key]
|
||||
|
||||
if value.is_a?(Proc)
|
||||
# call the proc
|
||||
value = (value.arity == 0) ? value.call : value.call(self)
|
||||
|
||||
# memozie if possible
|
||||
obj[key] = value if obj.respond_to?(:[]=)
|
||||
end
|
||||
|
||||
value
|
||||
end
|
||||
|
||||
def harden(value)
|
||||
value = value.to_liquid
|
||||
value.context = self if value.respond_to?(:context=)
|
||||
return value
|
||||
end
|
||||
end # lookup_and_evaluate
|
||||
|
||||
def squash_instance_assigns_with_environments
|
||||
@scopes.last.each_key do |k|
|
||||
@@ -256,7 +257,6 @@ module Liquid
|
||||
end
|
||||
end
|
||||
end # squash_instance_assigns_with_environments
|
||||
|
||||
end # Context
|
||||
|
||||
end # Liquid
|
||||
|
||||
@@ -20,9 +20,10 @@ module Liquid
|
||||
# Your drop can either implement the methods sans any parameters or implement the before_method(name) method which is a
|
||||
# catch all.
|
||||
class Drop
|
||||
attr_writer :context
|
||||
|
||||
EMPTY_STRING = ''.freeze
|
||||
METHOD_BLACKLIST = [:dup, :clone, :singleton_class, :eval, :class_eval, :`, :inspect]
|
||||
|
||||
attr_writer :context
|
||||
|
||||
# Catch all for the method
|
||||
def before_method(method)
|
||||
@@ -47,5 +48,9 @@ module Liquid
|
||||
end
|
||||
|
||||
alias :[] :invoke_drop
|
||||
|
||||
METHOD_BLACKLIST.each do |blacklisted|
|
||||
define_method(blacklisted) {nil}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,8 +6,6 @@ module Liquid
|
||||
if markup =~ Syntax
|
||||
@variable_name = $1
|
||||
@collection_name = $2
|
||||
@idx_i = "#{$1}-#{$2}-i"
|
||||
@idx_col = "#{$1}-#{$2}-c"
|
||||
@attributes = {}
|
||||
markup.scan(TagAttributes) do |key, value|
|
||||
@attributes[key] = value
|
||||
@@ -20,8 +18,6 @@ module Liquid
|
||||
end
|
||||
|
||||
def render(context)
|
||||
context.registers[:tablerowloop] ||= Hash.new(0)
|
||||
|
||||
collection = context[@collection_name] or return ''
|
||||
|
||||
from = @attributes['offset'] ? context[@attributes['offset']].to_i : 0
|
||||
@@ -36,15 +32,26 @@ module Liquid
|
||||
row = 1
|
||||
col = 0
|
||||
|
||||
result = ["<tr class=\"row1\">\n"]
|
||||
result = "<tr class=\"row1\">\n"
|
||||
context.stack do
|
||||
|
||||
context.registers[:tablerowloop][@idx]
|
||||
context['tablerowloop'] = lambda { Tablerowloop.new(@idx_i, @idx_col, length) }
|
||||
collection.each_with_index do |item, index|
|
||||
context.registers[:tablerowloop][@idx_i] = index
|
||||
context.registers[:tablerowloop][@idx_col] = col
|
||||
context[@variable_name] = item
|
||||
context[@variable_name] = item
|
||||
context['tablerowloop'] = {
|
||||
'length' => length,
|
||||
'index' => index + 1,
|
||||
'index0' => index,
|
||||
'col' => col + 1,
|
||||
'col0' => col,
|
||||
'index0' => index,
|
||||
'rindex' => length - index,
|
||||
'rindex0' => length - index - 1,
|
||||
'first' => (index == 0),
|
||||
'last' => (index == length - 1),
|
||||
'col_first' => (col == 0),
|
||||
'col_last' => (col == cols - 1)
|
||||
}
|
||||
|
||||
|
||||
col += 1
|
||||
|
||||
@@ -61,58 +68,6 @@ module Liquid
|
||||
result << "</tr>\n"
|
||||
result
|
||||
end
|
||||
|
||||
|
||||
|
||||
private
|
||||
|
||||
class Tablerowloop < Liquid::Drop
|
||||
attr_accessor :length
|
||||
|
||||
def initialize(idx_i, idx_col, length)
|
||||
@idx_i, @idx_col, @length = idx_i, idx_col, length
|
||||
end
|
||||
|
||||
def index
|
||||
@context.registers[:tablerowloop][@idx_i] + 1
|
||||
end
|
||||
|
||||
def index0
|
||||
@context.registers[:tablerowloop][@idx_i]
|
||||
end
|
||||
|
||||
def rindex
|
||||
length - @context.registers[:tablerowloop][@idx_i]
|
||||
end
|
||||
|
||||
def rindex0
|
||||
length - @context.registers[:tablerowloop][@idx_i] - 1
|
||||
end
|
||||
|
||||
def first
|
||||
(@context.registers[:tablerowloop][@idx_i] == 0)
|
||||
end
|
||||
|
||||
def last
|
||||
(@context.registers[:tablerowloop][@idx_i] == length - 1)
|
||||
end
|
||||
|
||||
def col
|
||||
@context.registers[:tablerowloop][@idx_col] + 1
|
||||
end
|
||||
|
||||
def col0
|
||||
@context.registers[:tablerowloop][@idx_col]
|
||||
end
|
||||
|
||||
def col_first
|
||||
(@context.registers[:tablerowloop][@idx_col] == 0)
|
||||
end
|
||||
|
||||
def col_last
|
||||
(@context.registers[:tablerowloop][@idx_col] == cols - 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Template.register_tag('tablerow', TableRow)
|
||||
|
||||
@@ -31,7 +31,7 @@ module Liquid
|
||||
context.stack do
|
||||
execute_else_block = true
|
||||
|
||||
output = []
|
||||
output = ''
|
||||
@blocks.each do |block|
|
||||
if block.else?
|
||||
return render_all(block.attachment, context) if execute_else_block
|
||||
|
||||
@@ -50,8 +50,7 @@ module Liquid
|
||||
if markup =~ Syntax
|
||||
@variable_name = $1
|
||||
@collection_name = $2
|
||||
@name = "#{$1}-#{$2}"
|
||||
@idx = "#{@name}-i"
|
||||
@name = "#{$1}-#{$2}"
|
||||
@reversed = $3
|
||||
@attributes = {}
|
||||
markup.scan(TagAttributes) do |key, value|
|
||||
@@ -88,13 +87,14 @@ module Liquid
|
||||
limit = context[@attributes['limit']]
|
||||
to = limit ? limit.to_i + from : nil
|
||||
|
||||
|
||||
segment = Utils.slice_collection_using_each(collection, from, to)
|
||||
|
||||
return render_else(context) if segment.empty?
|
||||
|
||||
segment.reverse! if @reversed
|
||||
|
||||
result = []
|
||||
result = ''
|
||||
|
||||
length = segment.length
|
||||
|
||||
@@ -102,10 +102,17 @@ module Liquid
|
||||
context.registers[:for][@name] = from + segment.length
|
||||
|
||||
context.stack do
|
||||
context['forloop'] = lambda { Forloop.new(@name, @idx, length) }
|
||||
segment.each_with_index do |item, index|
|
||||
context.registers[:for][@idx] = index
|
||||
context[@variable_name] = item
|
||||
context['forloop'] = {
|
||||
'name' => @name,
|
||||
'length' => length,
|
||||
'index' => index + 1,
|
||||
'index0' => index,
|
||||
'rindex' => length - index,
|
||||
'rindex0' => length - index - 1,
|
||||
'first' => (index == 0),
|
||||
'last' => (index == length - 1) }
|
||||
|
||||
result << render_all(@for_block, context)
|
||||
|
||||
@@ -122,39 +129,6 @@ module Liquid
|
||||
|
||||
private
|
||||
|
||||
class Forloop < Liquid::Drop
|
||||
attr_accessor :name, :length
|
||||
|
||||
def initialize(name, idx, length)
|
||||
@name, @idx, @length = name, idx, length
|
||||
end
|
||||
|
||||
def index
|
||||
@context.registers[:for][@idx] + 1
|
||||
end
|
||||
|
||||
def index0
|
||||
@context.registers[:for][@idx]
|
||||
end
|
||||
|
||||
def rindex
|
||||
length - @context.registers[:for][@idx]
|
||||
end
|
||||
|
||||
def rindex0
|
||||
length - @context.registers[:for][@idx] - 1
|
||||
end
|
||||
|
||||
def first
|
||||
(@context.registers[:for][@idx] == 0)
|
||||
end
|
||||
|
||||
def last
|
||||
(@context.registers[:for][@idx] == length - 1)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def render_else(context)
|
||||
return @else_block ? [render_all(@else_block, context)] : ''
|
||||
end
|
||||
|
||||
@@ -121,7 +121,8 @@ module Liquid
|
||||
begin
|
||||
# render the nodelist.
|
||||
# for performance reasons we get a array back here. join will make a string out of it
|
||||
@root.render(context).join
|
||||
result = @root.render(context)
|
||||
result.respond_to?(:join) ? result.join : result
|
||||
ensure
|
||||
@errors = context.errors
|
||||
end
|
||||
|
||||
@@ -11,7 +11,7 @@ module Liquid
|
||||
# {{ user | link }}
|
||||
#
|
||||
class Variable
|
||||
FilterParser = /(?:#{FilterSeparator}|(?:\s*(?!(?:#{FilterSeparator}))(?:#{QuotedFragment}|\S+)\s*)+)/o
|
||||
FilterParser = /(?:#{FilterSeparator}|(?:\s*(?:#{QuotedFragment}|#{ArgumentSeparator})\s*)+)/o
|
||||
attr_accessor :filters, :name
|
||||
|
||||
def initialize(markup)
|
||||
|
||||
Binary file not shown.
@@ -4,8 +4,8 @@ require File.dirname(__FILE__) + '/theme_runner'
|
||||
|
||||
profiler = ThemeRunner.new
|
||||
|
||||
Benchmark.bm do |x|
|
||||
# x.report("parse:") { 100.times { profiler.compile } }
|
||||
Benchmark.bmbm do |x|
|
||||
x.report("parse:") { 100.times { profiler.compile } }
|
||||
x.report("parse & run:") { 100.times { profiler.run } }
|
||||
end
|
||||
|
||||
|
||||
@@ -6,12 +6,14 @@ profiler = ThemeRunner.new
|
||||
|
||||
puts 'Running profiler...'
|
||||
|
||||
results = profiler.run_profile
|
||||
results = profiler.run
|
||||
|
||||
puts 'Success'
|
||||
puts
|
||||
|
||||
filename = (ENV['TMP'] || '/tmp') + "/callgrind.liquid.txt"
|
||||
File.open(filename, "w+") do |fp|
|
||||
RubyProf::CallTreePrinter.new(results).print(fp, :print_file => true)
|
||||
[RubyProf::FlatPrinter, RubyProf::GraphPrinter, RubyProf::GraphHtmlPrinter, RubyProf::CallTreePrinter].each do |klass|
|
||||
filename = (ENV['TMP'] || '/tmp') + (klass.name.include?('Html') ? "/liquid.#{klass.name.downcase}.html" : "/callgrind.liquid.#{klass.name.downcase}.txt")
|
||||
filename.gsub!(/:+/, '_')
|
||||
File.open(filename, "w+") { |fp| klass.new(results).print(fp, :print_file => true) }
|
||||
$stderr.puts "wrote #{klass.name} output to #{filename}"
|
||||
end
|
||||
$stderr.puts "wrote RubyProf::CallTreePrinter output to #{filename}"
|
||||
|
||||
@@ -31,6 +31,7 @@ class ThemeRunner
|
||||
# Dup assigns because will make some changes to them
|
||||
|
||||
@tests.each do |liquid, layout, template_name|
|
||||
|
||||
tmpl = Liquid::Template.new
|
||||
tmpl.parse(liquid)
|
||||
tmpl = Liquid::Template.new
|
||||
@@ -53,7 +54,7 @@ class ThemeRunner
|
||||
|
||||
|
||||
def run_profile
|
||||
RubyProf.measure_mode = RubyProf::PROCESS_TIME
|
||||
RubyProf.measure_mode = RubyProf::WALL_TIME
|
||||
|
||||
# Dup assigns because will make some changes to them
|
||||
assigns = Database.tables.dup
|
||||
|
||||
@@ -254,16 +254,12 @@ class ContextTest < Test::Unit::TestCase
|
||||
@context['test'] = {'test' => [1,2,3,4,5]}
|
||||
|
||||
assert_equal 1, @context['test.test[0]']
|
||||
end
|
||||
|
||||
def test_recoursive_array_notation_for_hash
|
||||
@context['test'] = [{'test' => 'worked'}]
|
||||
|
||||
assert_equal 'worked', @context['test[0].test']
|
||||
end
|
||||
|
||||
|
||||
|
||||
def test_hash_to_array_transition
|
||||
@context['colors'] = {
|
||||
'Blue' => ['003366','336699', '6699CC', '99CCFF'],
|
||||
@@ -319,7 +315,7 @@ class ContextTest < Test::Unit::TestCase
|
||||
@context['nested'] = {'var' => 'tags'}
|
||||
@context['products'] = {'count' => 5, 'tags' => ['deepsnow', 'freestyle'] }
|
||||
|
||||
#assert_equal 'deepsnow', @context['products[var].first']
|
||||
assert_equal 'deepsnow', @context['products[var].first']
|
||||
assert_equal 'freestyle', @context['products[nested.var].last']
|
||||
end
|
||||
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
require 'test_helper'
|
||||
|
||||
|
||||
class ParserTest < Test::Unit::TestCase
|
||||
include Liquid
|
||||
|
||||
|
||||
def test_strings
|
||||
assert_equal [[:id, "string"]], Parser.parse('"string"')
|
||||
assert_equal [[:id, "string"]], Parser.parse('\'string\'')
|
||||
end
|
||||
|
||||
def test_integer
|
||||
assert_equal [[:id, 1]], Parser.parse('1')
|
||||
assert_equal [[:id, 100001]], Parser.parse('100001')
|
||||
end
|
||||
|
||||
def test_float
|
||||
assert_equal [[:id, 1.1]], Parser.parse('1.1')
|
||||
assert_equal [[:id, 1.55435]], Parser.parse('1.55435')
|
||||
end
|
||||
|
||||
def test_null
|
||||
assert_equal [[:id, nil]], Parser.parse('null')
|
||||
assert_equal [[:id, nil]], Parser.parse('nil')
|
||||
end
|
||||
|
||||
def test_bool
|
||||
assert_equal [[:id, true]], Parser.parse('true')
|
||||
assert_equal [[:id, false]], Parser.parse('false')
|
||||
end
|
||||
|
||||
def test_ranges
|
||||
assert_equal [[:id, 1], [:id, 5], [:range, nil]], Parser.parse('(1..5)')
|
||||
assert_equal [[:id, 100], [:id, 500], [:range, nil]], Parser.parse('(100..500)')
|
||||
end
|
||||
|
||||
def test_ranges_with_lookups
|
||||
assert_equal [[:id, 1], [:id, "test"], [:lookup, nil], [:range, nil]], Parser.parse('(1..test)')
|
||||
end
|
||||
|
||||
def test_lookups
|
||||
assert_equal [[:id, "variable"], [:lookup, nil]], Parser.parse('variable')
|
||||
assert_equal [[:id, "underscored_variable"], [:lookup, nil]], Parser.parse('underscored_variable')
|
||||
end
|
||||
|
||||
def test_global_hash
|
||||
assert_equal [[:id, true], [:lookup, nil]], Parser.parse('[true]')
|
||||
|
||||
assert_equal [[:id, "string"], [:lookup, nil]], Parser.parse('["string"]')
|
||||
assert_equal [[:id, 5.55], [:lookup, nil]], Parser.parse('[5.55]')
|
||||
assert_equal [[:id, 0], [:lookup, nil]], Parser.parse('[0]')
|
||||
assert_equal [[:id, "variable"], [:lookup, nil], [:lookup, nil]], Parser.parse('[variable]')
|
||||
end
|
||||
|
||||
def test_descent
|
||||
assert_equal [[:id, "variable1"], [:lookup, nil], [:id, "variable2"], [:call, nil]], Parser.parse('variable1.variable2')
|
||||
assert_equal [[:id, "variable1"], [:lookup, nil], [:id, "variable2"], [:call, nil], [:id, "variable3"], [:call, nil]], Parser.parse('variable1.variable2.variable3')
|
||||
end
|
||||
|
||||
def test_descent_hash
|
||||
assert_equal [[:id, "variable1"], [:lookup, nil], [:id, "variable2"], [:call, nil]], Parser.parse('variable1["variable2"]')
|
||||
assert_equal [[:id, "variable1"], [:lookup, nil], [:id, "variable2"], [:lookup, nil], [:call, nil]], Parser.parse('variable1[variable2]')
|
||||
end
|
||||
|
||||
def test_buildin
|
||||
assert_equal [[:id, "first"], [:lookup, nil]], Parser.parse('first')
|
||||
|
||||
assert_equal [[:id, "var"], [:lookup, nil], [:buildin, "first"]], Parser.parse('var.first')
|
||||
assert_equal [[:id, "var"], [:lookup, nil], [:buildin, "last"]], Parser.parse('var.last')
|
||||
assert_equal [[:id, "var"], [:lookup, nil], [:buildin, "size"]], Parser.parse('var.size')
|
||||
|
||||
end
|
||||
|
||||
def test_descent_hash_descent
|
||||
assert_equal [[:id, "variable1"], [:lookup, nil], [:id, "test1"], [:lookup, nil], [:id, "test2"], [:call, nil], [:call, nil]],
|
||||
Parser.parse('variable1[test1.test2]'), "resolove: variable1[test1.test2]"
|
||||
|
||||
# assert_equal [[:id, "variable1"], [:lookup, nil], [:id, "test1"], [:lookup, nil], [:id, "test2"], [:call, nil], [:call, nil]],
|
||||
# Parser.parse('variable1[test1["test2"]]'), 'resolove: variable1[test1["test2"]]'
|
||||
|
||||
# assert_equal [[:id, "variable1"], [:lookup, nil], [:id, "test1"], [:lookup, nil], [:id, "test2"], [:lookup, nil], [:call, nil], [:call, nil]],
|
||||
# Parser.parse('variable1[test1[test2]]'), "resolove: variable1[test1[test2]]"
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
@@ -39,7 +39,7 @@ class ParsingQuirksTest < Test::Unit::TestCase
|
||||
|
||||
def test_meaningless_parens
|
||||
assigns = {'b' => 'bar', 'c' => 'baz'}
|
||||
markup = "a == 'foo' or b == 'bar' and c == 'baz' or false"
|
||||
markup = "a == 'foo' or (b == 'bar' and c == 'baz') or false"
|
||||
assert_template_result(' YES ',"{% if #{markup} %} YES {% endif %}", assigns)
|
||||
end
|
||||
|
||||
|
||||
@@ -66,6 +66,10 @@ class VariableTest < Test::Unit::TestCase
|
||||
var = Variable.new('hello|textileze|paragraph')
|
||||
assert_equal 'hello', var.name
|
||||
assert_equal [[:textileze,[]], [:paragraph,[]]], var.filters
|
||||
|
||||
var = Variable.new("hello|replace:'foo','bar'|textileze")
|
||||
assert_equal 'hello', var.name
|
||||
assert_equal [[:replace, ["'foo'", "'bar'"]], [:textileze, []]], var.filters
|
||||
end
|
||||
|
||||
def test_symbol
|
||||
|
||||
Reference in New Issue
Block a user