解析 ERB 文件的库

Dou*_*ers 5 ruby parsing lex erb

我试图以 Hpricot/Nokogiri 类型的方式解析而不是评估 rails ERB 文件。我试图解析的文件包含与使用 ERB(标准 Rails 视图文件)生成的动态内容混合的 HTML 片段ERB 符号、<%、<%= 等,就好像它们是 html/xml 标签一样。

理想情况下,我会得到一个类似于 DOM 的结构,其中 <%, <%= 等符号将作为它们自己的节点类型包含在内。

我知道可以使用正则表达式将某些东西组合在一起,但我正在寻找更可靠的东西,因为我正在开发一个工具,我需要在一个非常大的视图代码库上运行,其中 html 内容和 erb 内容是重要的。

例如,内容如下:

等等等等等等
<div>我的好文字 <%= my_dynamic_expression %></div>

将返回一个树结构,如:

根
 - text_node(等等等等)
 - 元素(div)
    - text_node(我的好文字)
        - erb_node (<%=)

Dou*_*ers 5

我最终通过使用 RLex 解决了这个问题,http: //raa.ruby-lang.org/project/ruby-lex/,lex的 ruby​​ 版本,具有以下语法:

%{

#define NUM 257

#define OPTOK 258
#define IDENT 259
#define OPETOK 260
#define CLSTOK 261
#define CLTOK 262
#define 浮点数 263
#define FIXNUM 264
#定义字265
#define STRING_DOUBLE_QUOTE 266
#define STRING_SINGLE_QUOTE 267

#define TAG_START 268
#define TAG_END 269
#define TAG_SELF_CONTAINED 270
#define ERB_BLOCK_START 271
#define ERB_BLOCK_END 272
#define ERB_STRING_START 273
#define ERB_STRING_END 274
#define TAG_NO_TEXT_START 275
#define TAG_NO_TEXT_END 276
#define WHITE_SPACE 277
%}

数字 [0-9]
空白的 [ ]
字母 [A-Za-z]
name1 [A-Za-z_]
name2 [A-Za-z_0-9]
valid_tag_character [A-Za-z0-9"'=@_():/] 
ignore_tags 样式|脚本
%%

{blank}+"\n" { return [ WHITE_SPACE, yytext ] } 
"\n"{blank}+ { return [ WHITE_SPACE, yytext ] } 
{blank}+"\n"{blank}+ { return [ WHITE_SPACE, yytext ] } 

"\r" { 返回 [ WHITE_SPACE, yytext ] } 
"\n" { return[ yytext[0], yytext[0..0] ] };
"\t" { return[ yytext[0], yytext[0..0] ] };

^{空白}+ { 返回 [ WHITE_SPACE, yytext ] }

{blank}+$ { return [ WHITE_SPACE, yytext ] };

"" { 返回 [ TAG_NO_TEXT_START, yytext ] }
"" { 返回 [ TAG_NO_TEXT_END, yytext ] }
"" { 返回 [ TAG_SELF_CONTAINED, yytext ] }
"" { 返回 [ TAG_SELF_CONTAINED, yytext ] }
"" { 返回 [ TAG_START, yytext ] }
"" { 返回 [ TAG_END, yytext ] }

"" { 返回 [ ERB_BLOCK_END, yytext ] }
"" { 返回 [ ERB_STRING_END, yytext ] }


{letter}+ { return [ WORD, yytext ] }


\".*\" { 返回 [ STRING_DOUBLE_QUOTE, yytext ] }
'.*' { 返回 [ STRING_SINGLE_QUOTE, yytext ] }
. { 返回 [ yytext[0], yytext[0..0] ] }

%%

这不是一个完整的语法,但就我的目的而言,定位和重新发送文本,它起作用了。我将语法与这段代码结合起来:

    text_handler = MakeYourOwnCallbackHandler.new

    l = Erblex.new
    l.yyin = File.open(file_name, "r")

    循环做
      a,v = l.yylex
      如果 a == 0 则中断

      if( a < 字 )
        text_handler.character( v.to_s, a )
      别的
        案例一
        当 WORD
          text_handler.text( v.to_s )
        当 TAG_START
          text_handler.start_tag( v.to_s )
        当TAG_END
          text_handler.end_tag( v.to_s )
        当空格
          text_handler.white_space( v.to_s )
        当 ERB_BLOCK_START
          text_handler.erb_block_start( v.to_s )
        当 ERB_BLOCK_END
          text_handler.erb_block_end( v.to_s )      
        当 ERB_STRING_START
          text_handler.erb_string_start( v.to_s )
        当 ERB_STRING_END
          self.text_handler.erb_string_end( v.to_s )
        当 TAG_NO_TEXT_START
          text_handler.ignorable_tag_start( v.to_s )
        当TAG_NO_TEXT_END
          text_handler.ignorable_tag_end( v.to_s )
        当STRING_DOUBLE_QUOTE
          text_handler.string_double_quote( v.to_s )
        当STRING_SINGLE_QUOTE
          text_handler.string_single_quote( v.to_s )
        当 TAG_SELF_CONTAINED
          text_handler.tag_self_contained( v.to_s )
        结尾
      结尾  
    结尾