Parsing Javascript using Ruby code [closed]
Asked Answered
T

3

10

I'm writing a test code in Ruby and trying to parse a HTML source file of a website. It has a JavaScript variable which I can use to compare it against other values. For example:

<script type="text/javascript" language="JavaScript">
  function GetParam(name) {   
    var req_var = {
      a: 'xyz', 
      b: 'yy.com', 
      c: 'en', 
      d:0, 
      e: 'y'
     };
  }
</script>

Here I want to extract the variable req_var from this function. Is it possible to do that? If so can anyone please help me with that?

Turley answered 9/2, 2011 at 0:29 Comment(2)
You have used the Nokogiri tag, so I'm not sure what you mean by "extract the variable req_var from this function". Do you need help using Nokogiri to find this script block? What do you want to get from the HTML, just the text of variable named req_var? Do you want to convert it into a Ruby Hash?Elison
I'm using Nokogiri in the same code to do some other html parsing. So,ideally if I can use Nokogiri, it'd be great. If I can convert it into a ruby hash it'd be great.Turley
U
9

javascript parser in ruby

Uveitis answered 9/2, 2011 at 0:35 Comment(0)
P
4

You could use a regular expression to parse it out like this:

k = "function GetParam(name) { var req_var = { a: 'xyz' , b: 'yy.com' , c: 'en' , d:0 , e: 'y'}; }"
variable = k.match(/var\s+req_var\s+=\s+(.*?);/m)[1]
p variable

=> "{ a: 'xyz' , b: 'yy.com' , c: 'en' , d:0 , e: 'y'}"
Photoconductivity answered 9/2, 2011 at 0:37 Comment(2)
This might work for some very constrained bits of JavaScript, but it's not generally possible to parse something like JavaScript code (or any programming language) with just a regular expression. (You may know that @Pan Thomakos, of course, but I'm typing this comment for the benefit of young, impressionable people who may read the answer in years to come.)Titleholder
That's true, but this seems like a constrained enough case, he doesn't need to parse an entire javascript program, he just needs the values between 'var req_var =' and ';'.Photoconductivity
M
0

rkelly gem threw an exception for me, so I used the fork rkelly-remix -- you have to uninstall the original one because they use the same name:

gem uninstall rkelly
gem install rkelly-remix

I had the following JS code:

  var xpos = 0;
  var ypos = 0;
  var city = 'Parish';
  var cashSaldo = '0.00';
  var bankSaldo = '';
  var address = 'Lot: 0 - 0';
  var simplemode = true;
  var email_reminder = true;
  var text_citylist = 'Take a cab to';
  var text_nostreet = 'Lot';
  var text_lotpos = 'Lot:';
  var text_products_title = 'Products';
  var text_products_subtitle = 'Produce and set prices';
  var text_title = 'Miniconomy';
  var text_has_harbor = 'This city has a harbor';
  var products = {"gron":{"ln":"Clay"},"stee":{"ln":"Brick"},"ijee":{"ln":"Iron Ore"},"boom":{"ln":"Tree"},"goud":{"ln":"Gold"},"olie":{"ln":"Oil"},"oven":{"ln":"Oven"},"ijze":{"ln":"Iron"},"hout":{"ln":"Wood"},"schi":{"ln":"Bulletproof Vest"},"benz":{"ln":"Gas"},"pomp":{"ln":"Pump"},"schr":{"ln":"Screwdriver"},"sche":{"ln":"Shovel"},"moto":{"ln":"Electrical Engine"},"plas":{"ln":"Plastic"},"zaag":{"ln":"Saw"},"mach":{"ln":"Machine"},"chip":{"ln":"Chip"},"tele":{"ln":"Telephone"},"came":{"ln":"Camera"},"alar":{"ln":"Alarm"},"glas":{"ln":"Glass"}};
  var isChristmas = 0;
  var newMap = 1;

And this is the code I had to write to parse it:

o = lambda do |x|
  next true if x == [:true]
  next x.size != 2 ? fail : eval(x[1].to_s) if x[0] == :lit || x[0] == :str
  next x.size != 2 ? fail : Hash[ x[1].map do |a,b,c|
    fail unless a == :property
    fail unless b.is_a? Symbol
    [eval(b.to_s).to_sym, o[c]]
  end ] if x.first == :object
  fail x.inspect
end

require "rkelly"

result = Hash[ RKelly::Parser.new.parse(my_js_code).to_sexp.map do |k, v|
  fail unless k == :var
  fail unless v.size == 1
  a, b, c = v.first
  fail unless a == :var_decl
  k, v = c
  fail unless k == :assign
  [b, o[v]]
end ]

That results in:

{:xpos=>0,
 :ypos=>0,
 :city=>"Parish",
 :cashSaldo=>"0.00",
 :bankSaldo=>"",
 :address=>"Lot: 0 - 0",
 :simplemode=>true,
 :email_reminder=>true,
 :text_citylist=>"Take a cab to",
 :text_nostreet=>"Lot",
 :text_lotpos=>"Lot:",
 :text_products_title=>"Products",
 :text_products_subtitle=>"Produce and set prices",
 :text_title=>"Miniconomy",
 :text_has_harbor=>"This city has a harbor",
 :products=>
  {:gron=>{:ln=>"Clay"},
   :stee=>{:ln=>"Brick"},
   :ijee=>{:ln=>"Iron Ore"},
   :boom=>{:ln=>"Tree"},
   :goud=>{:ln=>"Gold"},
   :olie=>{:ln=>"Oil"},
   :oven=>{:ln=>"Oven"},
   :ijze=>{:ln=>"Iron"},
   :hout=>{:ln=>"Wood"},
   :schi=>{:ln=>"Bulletproof Vest"},
   :benz=>{:ln=>"Gas"},
   :pomp=>{:ln=>"Pump"},
   :schr=>{:ln=>"Screwdriver"},
   :sche=>{:ln=>"Shovel"},
   :moto=>{:ln=>"Electrical Engine"},
   :plas=>{:ln=>"Plastic"},
   :zaag=>{:ln=>"Saw"},
   :mach=>{:ln=>"Machine"},
   :chip=>{:ln=>"Chip"},
   :tele=>{:ln=>"Telephone"},
   :came=>{:ln=>"Camera"},
   :alar=>{:ln=>"Alarm"},
   :glas=>{:ln=>"Glass"}},
 :isChristmas=>0,
 :newMap=>1}
Macri answered 4/9, 2018 at 4:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.