├── .editorconfig ├── .github └── workflows │ └── build.yml ├── .gitignore ├── .yardopts ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── appveyor.yml ├── benchmark ├── benchmark_helper.rb ├── css │ └── parser │ │ └── parser_bench.rb ├── fixtures │ ├── big.xml.gz │ ├── kaf.xml.gz │ └── with_entities.html ├── html │ └── lexer │ │ ├── lexer_bench.rb │ │ ├── string_average_bench.rb │ │ └── void_element_bench.rb ├── xml │ ├── lexer │ │ ├── io_average_bench.rb │ │ ├── lexer_bench.rb │ │ └── string_average_bench.rb │ ├── node_set │ │ └── push_bench.rb │ ├── parser │ │ ├── average_bench.rb │ │ ├── comparing_gems_bench.rb │ │ ├── html_bench.rb │ │ └── parser_bench.rb │ ├── pull_parser │ │ ├── average_bench.rb │ │ └── pull_parser_bench.rb │ └── traversal │ │ ├── average_each_node_bench.rb │ │ └── each_node_bench.rb └── xpath │ ├── compiler │ ├── big_xml_average_bench.rb │ ├── comparing_gems_bench.rb │ ├── concurrent_time_bench.rb │ ├── descendant_or_self_bench.rb │ └── simple_bench.rb │ ├── lexer │ └── lexer_bench.rb │ └── parser │ └── parser_bench.rb ├── checksum ├── .gitkeep ├── oga-0.1.0.gem.sha512 ├── oga-0.1.1-java.gem.sha512 ├── oga-0.1.1.gem.sha512 ├── oga-0.1.2-java.gem.sha512 ├── oga-0.1.2.gem.sha512 ├── oga-0.1.3-java.gem.sha512 ├── oga-0.1.3.gem.sha512 ├── oga-0.2.0-java.gem.sha512 ├── oga-0.2.0.gem.sha512 ├── oga-0.2.1-java.gem.sha512 ├── oga-0.2.1.gem.sha512 ├── oga-0.2.2-java.gem.sha512 ├── oga-0.2.2.gem.sha512 ├── oga-0.2.3-java.gem.sha512 ├── oga-0.2.3.gem.sha512 ├── oga-0.3.0-java.gem.sha512 ├── oga-0.3.0.gem.sha512 ├── oga-0.3.1-java.gem.sha512 ├── oga-0.3.1.gem.sha512 ├── oga-0.3.2-java.gem.sha512 ├── oga-0.3.2.gem.sha512 ├── oga-0.3.3-java.gem.sha512 ├── oga-0.3.3.gem.sha512 ├── oga-0.3.4-java.gem.sha512 ├── oga-0.3.4.gem.sha512 ├── oga-1.0.0-java.gem.sha512 ├── oga-1.0.0.gem.sha512 ├── oga-1.0.1-java.gem.sha512 ├── oga-1.0.1.gem.sha512 ├── oga-1.0.2-java.gem.sha512 ├── oga-1.0.2.gem.sha512 ├── oga-1.0.3-java.gem.sha512 ├── oga-1.0.3.gem.sha512 ├── oga-1.1.0-java.gem.sha512 ├── oga-1.1.0.gem.sha512 ├── oga-1.2.0-java.gem.sha512 ├── oga-1.2.0.gem.sha512 ├── oga-1.2.1-java.gem.sha512 ├── oga-1.2.1.gem.sha512 ├── oga-1.2.2-java.gem.sha512 ├── oga-1.2.2.gem.sha512 ├── oga-1.2.3-java.gem.sha512 ├── oga-1.2.3.gem.sha512 ├── oga-1.3.0-java.gem.sha512 ├── oga-1.3.0.gem.sha512 ├── oga-1.3.1-java.gem.sha512 ├── oga-1.3.1.gem.sha512 ├── oga-2.0.0-java.gem.sha512 ├── oga-2.0.0.gem.sha512 ├── oga-2.1-java.gem.sha512 ├── oga-2.1.gem.sha512 ├── oga-2.10-java.gem.sha512 ├── oga-2.10.gem.sha512 ├── oga-2.11-java.gem.sha512 ├── oga-2.11.gem.sha512 ├── oga-2.12-java.gem.sha512 ├── oga-2.12.gem.sha512 ├── oga-2.13-java.gem.sha512 ├── oga-2.13.gem.sha512 ├── oga-2.14-java.gem.sha512 ├── oga-2.14.gem.sha512 ├── oga-2.15-java.gem.sha512 ├── oga-2.15.gem.sha512 ├── oga-2.16-java.gem.sha512 ├── oga-2.16.gem.sha512 ├── oga-2.17-java.gem.sha512 ├── oga-2.17.gem.sha512 ├── oga-2.2-java.gem.sha512 ├── oga-2.2.gem.sha512 ├── oga-2.3-java.gem.sha512 ├── oga-2.3.gem.sha512 ├── oga-2.4-java.gem.sha512 ├── oga-2.4.gem.sha512 ├── oga-2.5-java.gem.sha512 ├── oga-2.5.gem.sha512 ├── oga-2.6-java.gem.sha512 ├── oga-2.6.gem.sha512 ├── oga-2.7-java.gem.sha512 ├── oga-2.7.gem.sha512 ├── oga-2.8-java.gem.sha512 ├── oga-2.8.gem.sha512 ├── oga-2.9-java.gem.sha512 ├── oga-2.9.gem.sha512 ├── oga-3.0-java.gem.sha512 ├── oga-3.0.gem.sha512 ├── oga-3.1-java.gem.sha512 ├── oga-3.1.gem.sha512 ├── oga-3.2-java.gem.sha512 ├── oga-3.2.gem.sha512 ├── oga-3.3-java.gem.sha512 ├── oga-3.3.gem.sha512 ├── oga-3.4-java.gem.sha512 └── oga-3.4.gem.sha512 ├── doc ├── .gitkeep ├── css │ ├── .gitkeep │ └── common.css ├── css_selectors.md ├── manually_creating_documents.md ├── migrating_from_nokogiri.md └── xml_namespaces.md ├── ext ├── c │ ├── extconf.rb │ ├── lexer.h │ ├── lexer.rl │ ├── liboga.c │ └── liboga.h ├── java │ ├── Liboga.java │ └── org │ │ └── liboga │ │ └── xml │ │ └── Lexer.rl └── ragel │ └── base_lexer.rl ├── lib ├── oga.rb └── oga │ ├── blacklist.rb │ ├── css │ ├── lexer.rl │ └── parser.rll │ ├── entity_decoder.rb │ ├── html │ ├── entities.rb │ ├── parser.rb │ └── sax_parser.rb │ ├── lru.rb │ ├── oga.rb │ ├── ruby │ ├── generator.rb │ └── node.rb │ ├── version.rb │ ├── whitelist.rb │ ├── xml │ ├── attribute.rb │ ├── cdata.rb │ ├── character_node.rb │ ├── comment.rb │ ├── default_namespace.rb │ ├── doctype.rb │ ├── document.rb │ ├── element.rb │ ├── entities.rb │ ├── expanded_name.rb │ ├── generator.rb │ ├── html_void_elements.rb │ ├── lexer.rb │ ├── namespace.rb │ ├── node.rb │ ├── node_set.rb │ ├── parser.rll │ ├── processing_instruction.rb │ ├── pull_parser.rb │ ├── querying.rb │ ├── sax_parser.rb │ ├── text.rb │ ├── to_xml.rb │ ├── traversal.rb │ └── xml_declaration.rb │ └── xpath │ ├── compiler.rb │ ├── context.rb │ ├── conversion.rb │ ├── lexer.rl │ └── parser.rll ├── oga.gemspec ├── profile ├── gnuplot │ └── memory_time.gpi ├── plot.sh ├── profile_helper.rb ├── samples │ ├── .gitkeep │ └── xml │ │ ├── lexer │ │ └── .gitkeep │ │ ├── parser │ │ └── .gitkeep │ │ └── pull_parser │ │ └── .gitkeep └── xml │ ├── lexer │ ├── big_xml.rb │ └── big_xml_io.rb │ ├── parser │ └── big_xml.rb │ └── pull_parser │ └── big_xml.rb ├── spec ├── oga │ ├── blacklist_spec.rb │ ├── css │ │ ├── compiler │ │ │ ├── axes_spec.rb │ │ │ ├── classes_spec.rb │ │ │ ├── ids_spec.rb │ │ │ ├── operators_spec.rb │ │ │ ├── paths_spec.rb │ │ │ ├── predicates_spec.rb │ │ │ └── pseudo_classes │ │ │ │ ├── empty_spec.rb │ │ │ │ ├── first_child_spec.rb │ │ │ │ ├── first_of_type_spec.rb │ │ │ │ ├── last_child_spec.rb │ │ │ │ ├── last_of_type_spec.rb │ │ │ │ ├── nth_child_spec.rb │ │ │ │ ├── nth_last_child_spec.rb │ │ │ │ ├── nth_last_of_type_spec.rb │ │ │ │ ├── nth_of_type_spec.rb │ │ │ │ ├── nth_spec.rb │ │ │ │ ├── only_child_spec.rb │ │ │ │ ├── only_of_type_spec.rb │ │ │ │ └── root_spec.rb │ │ ├── lexer │ │ │ ├── axes_spec.rb │ │ │ ├── namespaces_spec.rb │ │ │ ├── operators_spec.rb │ │ │ ├── paths_spec.rb │ │ │ ├── predicates_spec.rb │ │ │ ├── pseudo_classes_spec.rb │ │ │ └── strings_spec.rb │ │ ├── lexer_spec.rb │ │ └── parser │ │ │ ├── axes_spec.rb │ │ │ ├── cache_spec.rb │ │ │ ├── classes_spec.rb │ │ │ ├── ids_spec.rb │ │ │ ├── operators_spec.rb │ │ │ ├── paths_spec.rb │ │ │ ├── predicates_spec.rb │ │ │ ├── pseudo_classes │ │ │ ├── empty_spec.rb │ │ │ ├── first_child_spec.rb │ │ │ ├── first_of_type_spec.rb │ │ │ ├── last_child_spec.rb │ │ │ ├── last_of_type_spec.rb │ │ │ ├── not_spec.rb │ │ │ ├── nth_child_spec.rb │ │ │ ├── nth_last_child_spec.rb │ │ │ ├── nth_last_of_type_spec.rb │ │ │ ├── nth_of_type_spec.rb │ │ │ ├── nth_spec.rb │ │ │ ├── only_child_spec.rb │ │ │ ├── only_of_type_spec.rb │ │ │ └── root_spec.rb │ │ │ └── wildcards_spec.rb │ ├── entity_decoder_spec.rb │ ├── html │ │ ├── entities_spec.rb │ │ ├── lexer │ │ │ ├── attributes_spec.rb │ │ │ ├── closing_mismatch_spec.rb │ │ │ ├── closing_rules │ │ │ │ ├── body_spec.rb │ │ │ │ ├── caption_spec.rb │ │ │ │ ├── colgroup_spec.rb │ │ │ │ ├── dd_spec.rb │ │ │ │ ├── dt_spec.rb │ │ │ │ ├── head_spec.rb │ │ │ │ ├── li_spec.rb │ │ │ │ ├── optgroup_spec.rb │ │ │ │ ├── option_spec.rb │ │ │ │ ├── p_spec.rb │ │ │ │ ├── rb_spec.rb │ │ │ │ ├── rp_spec.rb │ │ │ │ ├── rt_spec.rb │ │ │ │ ├── rtc_spec.rb │ │ │ │ ├── table_spec.rb │ │ │ │ ├── tbody_spec.rb │ │ │ │ ├── td_spec.rb │ │ │ │ ├── tfoot_spec.rb │ │ │ │ ├── th_spec.rb │ │ │ │ ├── thead_spec.rb │ │ │ │ ├── tr_spec.rb │ │ │ │ └── ul_spec.rb │ │ │ ├── elements_spec.rb │ │ │ ├── inline_javascript_spec.rb │ │ │ ├── script_spec.rb │ │ │ ├── style_spec.rb │ │ │ └── void_elements_spec.rb │ │ ├── parser │ │ │ └── element_spec.rb │ │ └── sax_parser_spec.rb │ ├── lru_spec.rb │ ├── oga_spec.rb │ ├── ruby │ │ ├── generator_spec.rb │ │ └── node_spec.rb │ ├── whitelist_spec.rb │ ├── xml │ │ ├── attribute_spec.rb │ │ ├── cdata_spec.rb │ │ ├── character_node_spec.rb │ │ ├── comment_spec.rb │ │ ├── doctype_spec.rb │ │ ├── document_spec.rb │ │ ├── element_spec.rb │ │ ├── entities_spec.rb │ │ ├── generator_spec.rb │ │ ├── lexer │ │ │ ├── cdata_spec.rb │ │ │ ├── comments_spec.rb │ │ │ ├── doctype_spec.rb │ │ │ ├── documents_spec.rb │ │ │ ├── elements_spec.rb │ │ │ ├── enumerator_spec.rb │ │ │ ├── general_spec.rb │ │ │ ├── invalid_elements_spec.rb │ │ │ ├── io_spec.rb │ │ │ ├── multibyte_spec.rb │ │ │ ├── processing_instruction_spec.rb │ │ │ ├── strict_spec.rb │ │ │ └── xml_declaration_spec.rb │ │ ├── namespace_spec.rb │ │ ├── node_set_spec.rb │ │ ├── node_spec.rb │ │ ├── parser │ │ │ ├── cdata_spec.rb │ │ │ ├── comments_spec.rb │ │ │ ├── doctype_spec.rb │ │ │ ├── documents_spec.rb │ │ │ ├── elements_spec.rb │ │ │ ├── error_spec.rb │ │ │ ├── hierarchy_spec.rb │ │ │ ├── html_void_elements_spec.rb │ │ │ ├── io_spec.rb │ │ │ ├── processing_instruction_spec.rb │ │ │ ├── text_spec.rb │ │ │ └── xml_declaration_spec.rb │ │ ├── processing_instruction_spec.rb │ │ ├── pull_parser │ │ │ ├── context_parsing_spec.rb │ │ │ ├── doctype_spec.rb │ │ │ ├── element_nesting_spec.rb │ │ │ ├── element_spec.rb │ │ │ ├── general_spec.rb │ │ │ └── processing_instruction_spec.rb │ │ ├── querying_spec.rb │ │ ├── sax_parser_spec.rb │ │ ├── text_spec.rb │ │ ├── to_xml_spec.rb │ │ ├── traversal_spec.rb │ │ └── xml_declaration_spec.rb │ └── xpath │ │ ├── compiler │ │ ├── axes │ │ │ ├── ancestor_or_self_spec.rb │ │ │ ├── ancestor_spec.rb │ │ │ ├── attribute_spec.rb │ │ │ ├── child_spec.rb │ │ │ ├── descendant_or_self_spec.rb │ │ │ ├── descendant_spec.rb │ │ │ ├── following_sibling_spec.rb │ │ │ ├── following_spec.rb │ │ │ ├── namespace_spec.rb │ │ │ ├── parent_spec.rb │ │ │ ├── preceding_sibling_spec.rb │ │ │ ├── preceding_spec.rb │ │ │ └── self_spec.rb │ │ ├── calls │ │ │ ├── boolean_spec.rb │ │ │ ├── ceiling_spec.rb │ │ │ ├── concat_spec.rb │ │ │ ├── contains_spec.rb │ │ │ ├── count_spec.rb │ │ │ ├── false_spec.rb │ │ │ ├── floor_spec.rb │ │ │ ├── id_spec.rb │ │ │ ├── lang_spec.rb │ │ │ ├── last_spec.rb │ │ │ ├── local_name_spec.rb │ │ │ ├── name_spec.rb │ │ │ ├── namespace_uri_spec.rb │ │ │ ├── normalize_space_spec.rb │ │ │ ├── not_spec.rb │ │ │ ├── number_spec.rb │ │ │ ├── position_spec.rb │ │ │ ├── round_spec.rb │ │ │ ├── starts_with_spec.rb │ │ │ ├── string_length_spec.rb │ │ │ ├── string_spec.rb │ │ │ ├── substring_after_spec.rb │ │ │ ├── substring_before_spec.rb │ │ │ ├── substring_spec.rb │ │ │ ├── sum_spec.rb │ │ │ ├── translate_spec.rb │ │ │ └── true_spec.rb │ │ ├── html_spec.rb │ │ ├── namespace_aliases_spec.rb │ │ ├── operators │ │ │ ├── add_spec.rb │ │ │ ├── and_spec.rb │ │ │ ├── div_spec.rb │ │ │ ├── eq_spec.rb │ │ │ ├── gt_spec.rb │ │ │ ├── gte_spec.rb │ │ │ ├── lt_spec.rb │ │ │ ├── lte_spec.rb │ │ │ ├── mod_spec.rb │ │ │ ├── mul_spec.rb │ │ │ ├── neq_spec.rb │ │ │ ├── or_spec.rb │ │ │ ├── pipe_spec.rb │ │ │ └── sub_spec.rb │ │ ├── paths_spec.rb │ │ ├── predicates_spec.rb │ │ ├── type_tests │ │ │ ├── comment_spec.rb │ │ │ ├── node_spec.rb │ │ │ ├── processing_instruction_spec.rb │ │ │ └── text_spec.rb │ │ ├── types │ │ │ ├── float_spec.rb │ │ │ ├── int_spec.rb │ │ │ └── string_spec.rb │ │ ├── variables_spec.rb │ │ └── wildcard_spec.rb │ │ ├── compiler_spec.rb │ │ ├── context_spec.rb │ │ ├── conversion_spec.rb │ │ ├── lexer │ │ ├── axes_spec.rb │ │ ├── calls_spec.rb │ │ ├── floats_spec.rb │ │ ├── general_spec.rb │ │ ├── integers_spec.rb │ │ ├── node_type_spec.rb │ │ ├── operators_spec.rb │ │ ├── predicates_spec.rb │ │ ├── strings_spec.rb │ │ └── variable_spec.rb │ │ └── parser │ │ ├── axes_spec.rb │ │ ├── cache_spec.rb │ │ ├── calls_spec.rb │ │ ├── grouping_spec.rb │ │ ├── operator_precedence_spec.rb │ │ ├── operators_spec.rb │ │ ├── paths_spec.rb │ │ ├── predicates_spec.rb │ │ ├── type_tests_spec.rb │ │ ├── variable_spec.rb │ │ └── wildcard_spec.rb ├── spec_helper.rb └── support │ ├── evaluation_helpers.rb │ ├── parsing_helpers.rb │ ├── simplecov.rb │ └── threading_helpers.rb └── task ├── build.rake ├── checksum.rake ├── coverage.rake ├── doc.rake ├── fixtures.rake ├── generate.rake ├── lexer.rake ├── parser.rake ├── tag.rake ├── test.rake └── todo.rake /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | indent_style = spaces 6 | trim_trailing_whitespace = true 7 | 8 | [*.{y,rb,rl,rll}] 9 | indent_size = 2 10 | 11 | [*.{h,c,java}] 12 | indent_size = 4 13 | 14 | [ext/c/*.rl] 15 | indent_size = 4 16 | 17 | [ext/java/org/liboga/xml/*.rl] 18 | indent_size = 4 19 | 20 | [ext/ragel/*.rl] 21 | indent_size = 4 22 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Test 3 | on: push 4 | 5 | jobs: 6 | test: 7 | name: Run tests 8 | runs-on: ubuntu-latest 9 | strategy: 10 | fail-fast: false 11 | matrix: 12 | ruby: 13 | - '2.6' 14 | - '2.7' 15 | - '3.2' 16 | - jruby 17 | steps: 18 | - uses: actions/checkout@v3 19 | 20 | - uses: ruby/setup-ruby@v1 21 | with: 22 | ruby-version: ${{ matrix.ruby }} 23 | bundler-cache: true 24 | 25 | - run: sudo apt-get install -y ragel 26 | 27 | - run: bundle exec rake 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | yardoc 2 | coverage 3 | pkg 4 | Gemfile.lock 5 | 6 | lib/oga/xml/parser.rb 7 | lib/oga/xpath/lexer.rb 8 | lib/oga/xpath/parser.rb 9 | lib/oga/css/lexer.rb 10 | lib/oga/css/parser.rb 11 | 12 | lib/liboga.* 13 | 14 | benchmark/fixtures/big.xml 15 | benchmark/fixtures/kaf.xml 16 | 17 | profile/samples/xml/*.txt 18 | profile/samples/xml/*/*.txt 19 | *.so 20 | tmp 21 | 22 | ext/c/lexer.c 23 | ext/java/org/liboga/xml/Lexer.java 24 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | ./lib/oga/**/*.rb ./lib/oga.rb 2 | -m markdown 3 | -M kramdown 4 | -o yardoc 5 | -r ./README.md 6 | --protected 7 | --asset ./doc/css/common.css:css/common.css 8 | --verbose 9 | - 10 | ./doc/*.md 11 | LICENSE 12 | CONTRIBUTING.md 13 | CHANGELOG.md 14 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec 4 | 5 | group :benchmarking do 6 | gem 'ox', :platforms => [:mri, :rbx] 7 | gem 'nokogiri' 8 | end 9 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | require 'bundler/gem_tasks' 3 | require 'digest/sha2' 4 | require 'rake/clean' 5 | 6 | if Gem.win_platform? 7 | task :devkit do 8 | begin 9 | require 'devkit' 10 | rescue LoadError 11 | warn 'Failed to load devkit, installation might fail' 12 | end 13 | end 14 | 15 | task :compile => [:devkit] 16 | end 17 | 18 | GEMSPEC = Gem::Specification.load('oga.gemspec') 19 | 20 | if RUBY_PLATFORM == 'java' 21 | require 'rake/javaextensiontask' 22 | 23 | Rake::JavaExtensionTask.new('liboga', GEMSPEC) do |task| 24 | task.ext_dir = 'ext/java' 25 | task.target_version = '1.8' 26 | task.source_version = '1.8' 27 | end 28 | else 29 | require 'rake/extensiontask' 30 | 31 | Rake::ExtensionTask.new('liboga', GEMSPEC) do |task| 32 | task.ext_dir = 'ext/c' 33 | end 34 | end 35 | 36 | CLEAN.include( 37 | 'coverage', 38 | 'yardoc', 39 | 'lib/oga/xml/parser.rb', 40 | 'lib/oga/xpath/lexer.rb', 41 | 'lib/oga/xpath/parser.rb', 42 | 'lib/oga/css/lexer.rb', 43 | 'lib/oga/css/parser.rb', 44 | 'benchmark/fixtures/big.xml', 45 | 'profile/samples/**/*.txt', 46 | 'lib/liboga.*', 47 | 'tmp', 48 | 'ext/c/lexer.c', 49 | 'ext/java/org/liboga/xml/Lexer.java' 50 | ) 51 | 52 | Dir['./task/*.rake'].each do |task| 53 | import(task) 54 | end 55 | 56 | task :default => :test 57 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | --- 2 | image: Visual Studio 2017 3 | 4 | version: "{build}" 5 | 6 | install: 7 | - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-ragel" 8 | - SET PATH=C:\msys64\mingw64\bin;%PATH% 9 | - SET PATH=C:\Ruby%ruby_version%\bin;%PATH% 10 | - bundle install --retry 3 11 | 12 | build: off 13 | 14 | before_test: 15 | - ragel --version 16 | - ruby --version 17 | - gem --version 18 | - bundle --version 19 | 20 | test_script: 21 | - rake 22 | 23 | environment: 24 | matrix: 25 | - ruby_version: "22" 26 | - ruby_version: "22-x64" 27 | - ruby_version: "23" 28 | - ruby_version: "23-x64" 29 | - ruby_version: "24" 30 | - ruby_version: "24-x64" 31 | 32 | skip_tags: true 33 | -------------------------------------------------------------------------------- /benchmark/benchmark_helper.rb: -------------------------------------------------------------------------------- 1 | require 'bundler/setup' 2 | require 'stringio' 3 | require 'benchmark' 4 | require 'benchmark/ips' 5 | require 'oga' 6 | 7 | # @return [File] 8 | def big_xml_file 9 | File.open(File.expand_path('../fixtures/big.xml', __FILE__), 'r') 10 | end 11 | 12 | # @return [File] 13 | def big_kaf_file 14 | File.open(File.expand_path('../fixtures/kaf.xml', __FILE__), 'r') 15 | end 16 | 17 | # @return [String] 18 | def read_big_xml 19 | big_xml_file.read 20 | end 21 | 22 | # @return [String] 23 | def read_big_kaf 24 | big_kaf_file.read 25 | end 26 | 27 | # @return [String] 28 | def read_html 29 | return File.read(File.expand_path('../fixtures/with_entities.html', __FILE__)) 30 | end 31 | 32 | ## 33 | # Benchmarks the average runtime of the given block. 34 | # 35 | # @param [Fixnum] amount The amount of times to call the block. 36 | # @param [Fixnum] precision 37 | # 38 | def measure_average(amount = 10, precision = 3) 39 | timings = [] 40 | 41 | amount.times do |iter| 42 | timing = Benchmark.measure { yield }.real 43 | 44 | timings << timing.real 45 | 46 | puts "Iteration: #{iter + 1}: #{timing.real.round(precision)}" 47 | end 48 | 49 | average = timings.inject(:+) / timings.length 50 | 51 | puts 52 | puts "Iterations: #{amount}" 53 | puts "Average: #{average.round(precision)} sec" 54 | end 55 | -------------------------------------------------------------------------------- /benchmark/css/parser/parser_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | css = 'foo bar bar.some_class element#with_id[title="Foo"]' 4 | 5 | Benchmark.ips do |bench| 6 | bench.report 'without cache' do 7 | Oga::CSS::Parser.new(css).parse 8 | end 9 | 10 | bench.report 'with cache' do 11 | Oga::CSS::Parser.parse_with_cache(css) 12 | end 13 | 14 | bench.compare! 15 | end 16 | -------------------------------------------------------------------------------- /benchmark/fixtures/big.xml.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yorickpeterse/oga/6c4356f0f5af0212e9c6043b45b660b61fc624b4/benchmark/fixtures/big.xml.gz -------------------------------------------------------------------------------- /benchmark/fixtures/kaf.xml.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yorickpeterse/oga/6c4356f0f5af0212e9c6043b45b660b61fc624b4/benchmark/fixtures/kaf.xml.gz -------------------------------------------------------------------------------- /benchmark/html/lexer/lexer_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | html = read_html 4 | 5 | Benchmark.ips do |bench| 6 | bench.report 'lex HTML' do 7 | Oga::XML::Lexer.new(html, :html => true).advance { } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /benchmark/html/lexer/string_average_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | xml = read_big_xml 4 | 5 | measure_average do 6 | Oga::XML::Lexer.new(xml, :html => true).advance { } 7 | end 8 | -------------------------------------------------------------------------------- /benchmark/html/lexer/void_element_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | content = '' 4 | max_size = 5 * 1024 * 1024 5 | 6 | while content.bytesize <= max_size 7 | content << "
" 8 | end 9 | 10 | html = "#{content}" 11 | html_caps = "#{content.upcase}" 12 | 13 | Benchmark.ips do |bench| 14 | bench.report 'void elements' do 15 | Oga::XML::Lexer.new(html, :html => true).advance { } 16 | end 17 | 18 | bench.report 'void elements caps' do 19 | Oga::XML::Lexer.new(html_caps, :html => true).advance { } 20 | end 21 | 22 | bench.compare! 23 | end 24 | -------------------------------------------------------------------------------- /benchmark/xml/lexer/io_average_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | measure_average do 4 | Oga::XML::Lexer.new(big_xml_file).advance { } 5 | end 6 | -------------------------------------------------------------------------------- /benchmark/xml/lexer/lexer_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | xml = read_big_xml 4 | 5 | Benchmark.ips do |bench| 6 | bench.report '10MB as a String' do 7 | Oga::XML::Lexer.new(xml).advance { } 8 | end 9 | 10 | bench.report '10MB as an IO' do 11 | Oga::XML::Lexer.new(big_xml_file).advance { } 12 | end 13 | 14 | bench.compare! 15 | end 16 | -------------------------------------------------------------------------------- /benchmark/xml/lexer/string_average_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | xml = read_big_xml 4 | 5 | measure_average do 6 | Oga::XML::Lexer.new(xml).advance { } 7 | end 8 | -------------------------------------------------------------------------------- /benchmark/xml/node_set/push_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | # Assigning to an Array first saves the need (and overhead) of calling #push for 4 | # every iteration. 5 | initial = 20_000.times.map do |number| 6 | Oga::XML::Element.new(:name => number.to_s) 7 | end 8 | 9 | initial = Oga::XML::NodeSet.new(initial) 10 | 11 | Benchmark.ips do |bench| 12 | bench.report 'XML::NodeSet#push' do 13 | new_set = Oga::XML::NodeSet.new 14 | 15 | initial.each { |node| new_set << node } 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /benchmark/xml/parser/average_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | xml = read_big_xml 4 | 5 | measure_average do 6 | Oga::XML::Parser.new(xml).parse 7 | end 8 | -------------------------------------------------------------------------------- /benchmark/xml/parser/comparing_gems_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | require 'nokogiri' 4 | require 'ox' 5 | require 'rexml/document' 6 | 7 | xml = read_big_xml 8 | 9 | Benchmark.ips do |bench| 10 | bench.report 'Ox' do 11 | Ox.parse(xml) 12 | end 13 | 14 | bench.report 'Nokogiri' do 15 | Nokogiri::XML(xml) 16 | end 17 | 18 | bench.report 'Oga' do 19 | Oga::XML::Parser.new(xml).parse 20 | end 21 | 22 | bench.report 'REXML' do 23 | REXML::Document.new(xml) 24 | end 25 | 26 | bench.compare! 27 | end 28 | -------------------------------------------------------------------------------- /benchmark/xml/parser/html_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | require 'nokogiri' 4 | 5 | html = read_html 6 | 7 | Benchmark.ips do |bench| 8 | bench.report 'Oga' do 9 | Oga.parse_html(html) 10 | end 11 | 12 | bench.report 'Nokogiri' do 13 | Nokogiri::HTML(html) 14 | end 15 | 16 | bench.compare! 17 | end 18 | -------------------------------------------------------------------------------- /benchmark/xml/parser/parser_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | xml = read_big_xml 4 | 5 | Benchmark.ips do |bench| 6 | bench.report '10MB as a String' do 7 | Oga::XML::Parser.new(xml).parse 8 | end 9 | 10 | bench.report '10MB as an IO' do 11 | Oga::XML::Parser.new(big_xml_file).parse 12 | end 13 | 14 | bench.compare! 15 | end 16 | -------------------------------------------------------------------------------- /benchmark/xml/pull_parser/average_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | xml = read_big_xml 4 | 5 | measure_average do 6 | Oga::XML::PullParser.new(xml).parse { } 7 | end 8 | -------------------------------------------------------------------------------- /benchmark/xml/pull_parser/pull_parser_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | xml = read_big_xml 4 | 5 | Benchmark.ips do |bench| 6 | bench.report '10MB as a String' do 7 | Oga::XML::PullParser.new(xml).parse { } 8 | end 9 | 10 | bench.report '10MB as an IO' do 11 | Oga::XML::PullParser.new(big_xml_file).parse { } 12 | end 13 | 14 | bench.compare! 15 | end 16 | -------------------------------------------------------------------------------- /benchmark/xml/traversal/average_each_node_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | doc = Oga.parse_xml(big_xml_file) 4 | 5 | doc.each_node { } 6 | 7 | measure_average do 8 | doc.each_node { } 9 | end 10 | -------------------------------------------------------------------------------- /benchmark/xml/traversal/each_node_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | doc = Oga.parse_xml(big_xml_file) 4 | 5 | Benchmark.ips do |bench| 6 | bench.report 'each_node' do 7 | doc.each_node { } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /benchmark/xpath/compiler/big_xml_average_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | doc = Oga.parse_xml(big_xml_file) 4 | 5 | # Warm up any caches 6 | doc.xpath('descendant-or-self::location') 7 | 8 | measure_average do 9 | doc.xpath('descendant-or-self::location') 10 | end 11 | -------------------------------------------------------------------------------- /benchmark/xpath/compiler/comparing_gems_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | require 'nokogiri' 4 | require 'ox' 5 | require 'rexml/document' 6 | 7 | xml = '10' 8 | 9 | ox_doc = Ox.parse(xml) 10 | noko_doc = Nokogiri::XML(xml) 11 | oga_doc = Oga::XML::Parser.new(xml).parse 12 | rex_doc = REXML::Document.new(xml) 13 | 14 | ox_exp = 'number/^Text' 15 | xpath_exp = 'root/number/text()' 16 | 17 | Benchmark.ips do |bench| 18 | # Technically not XPath but it's the closest thing Ox provides. 19 | bench.report 'Ox' do 20 | ox_doc.locate(ox_exp) 21 | end 22 | 23 | bench.report 'Nokogiri' do 24 | noko_doc.xpath(xpath_exp) 25 | end 26 | 27 | bench.report 'Oga' do 28 | oga_doc.xpath(xpath_exp) 29 | end 30 | 31 | bench.report 'REXML' do 32 | REXML::XPath.match(rex_doc, xpath_exp) 33 | end 34 | 35 | bench.compare! 36 | end 37 | -------------------------------------------------------------------------------- /benchmark/xpath/compiler/concurrent_time_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | require 'thread' 3 | 4 | puts 'Preparing...' 5 | 6 | xml = read_big_kaf 7 | xpath = 'KAF/terms/term' 8 | xpath_ast = Oga::XPath::Parser.new(xpath).parse 9 | output = Queue.new 10 | 11 | stop = false 12 | threads = [] 13 | 14 | thread_count = ENV['THREADS'] ? ENV['THREADS'].to_i : 5 15 | sample_size = ENV['SAMPLES'] ? ENV['SAMPLES'].to_i : 10 16 | 17 | trap 'INT' do 18 | stop = true 19 | end 20 | 21 | # Parse these outside of the profiler 22 | documents = thread_count.times.map { Oga.parse_xml(xml) } 23 | 24 | puts 'Starting threads...' 25 | 26 | require 'profile' if ENV['PROFILE'] 27 | 28 | thread_count.times.each do 29 | threads << Thread.new do 30 | oga_doc = documents.pop 31 | compiler = Oga::XPath::Compiler.new 32 | block = compiler.compile(xpath_ast) 33 | 34 | sample_size.times do 35 | break if stop 36 | 37 | output << Benchmark.measure { block.call(oga_doc) } 38 | end 39 | end 40 | end 41 | 42 | threads.each(&:join) 43 | 44 | samples = [] 45 | 46 | until output.empty? 47 | samples << output.pop.real 48 | end 49 | 50 | average = samples.inject(:+) / samples.length 51 | 52 | puts "Samples: #{samples.length}" 53 | puts "Average: #{average.round(4)} seconds" 54 | -------------------------------------------------------------------------------- /benchmark/xpath/compiler/descendant_or_self_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | document = Oga.parse_html(read_html) 4 | 5 | Benchmark.ips do |bench| 6 | bench.report 'short form' do 7 | document.xpath('//meta') 8 | end 9 | 10 | bench.report 'long form' do 11 | document.xpath('descendant-or-self::meta') 12 | end 13 | 14 | bench.compare! 15 | end 16 | -------------------------------------------------------------------------------- /benchmark/xpath/compiler/simple_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | document = Oga.parse_xml('') 4 | query = 'root' 5 | 6 | Benchmark.ips do |bench| 7 | bench.report(query.inspect) do 8 | document.xpath(query) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /benchmark/xpath/lexer/lexer_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | xpath = '/wikimedia/projects/project[@name="Wikipedia"]/editions/edition/text()' 4 | 5 | Benchmark.ips do |bench| 6 | bench.report 'Wikipedia example' do 7 | Oga::XPath::Lexer.new(xpath).advance { } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /benchmark/xpath/parser/parser_bench.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../benchmark_helper' 2 | 3 | xpath = '/wikimedia/projects/project[@name="Wikipedia"]/editions/edition/text()' 4 | 5 | Benchmark.ips do |bench| 6 | bench.report 'without cache' do 7 | Oga::XPath::Parser.new(xpath).parse 8 | end 9 | 10 | bench.report 'with cache' do 11 | Oga::XPath::Parser.parse_with_cache(xpath) 12 | end 13 | 14 | bench.compare! 15 | end 16 | -------------------------------------------------------------------------------- /checksum/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yorickpeterse/oga/6c4356f0f5af0212e9c6043b45b660b61fc624b4/checksum/.gitkeep -------------------------------------------------------------------------------- /checksum/oga-0.1.0.gem.sha512: -------------------------------------------------------------------------------- 1 | 5f9b3632070e5c724a7603f12553f4ae8e0a1f537a74ccb0538ffbb10a5c08d348d55d43930394c0cf46932970e09205020ff9f2b4844c79895b395a0ed5df07 -------------------------------------------------------------------------------- /checksum/oga-0.1.1-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 26e515045b971afc9316c989e949ca5e5d097f76fbbbcfe28a90f5f1995ee773ddc6a47ad331771b63421bea70a13bcfa5d3a2fa4f25c7bd1d693a0f6577d0ee -------------------------------------------------------------------------------- /checksum/oga-0.1.1.gem.sha512: -------------------------------------------------------------------------------- 1 | 57f84bb186f93b1f3fb8a6ef885de6ecab8a752564c277a1fd64dde46172c0dc980cbb0b6a71d3bb629c709be26f3fb3fc9b4b36e4160915b2bc1629cb4a0f33 -------------------------------------------------------------------------------- /checksum/oga-0.1.2-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 7711326ffc0dcd904fecec36e5f3c1806e21fd91321def8c53da4cebefd36ceaaf8c93d04748528f5a8d525454a35c9b12d405ebb08f5cffe4987fb61a4dc172 -------------------------------------------------------------------------------- /checksum/oga-0.1.2.gem.sha512: -------------------------------------------------------------------------------- 1 | e734728c9fe05f17883f76f444325c770756d0c244f55c9b81e727f259b946aa7d3cd7a7eb8334193de2b9e1690f91614e78e61a11691624847911fc72ae4453 -------------------------------------------------------------------------------- /checksum/oga-0.1.3-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 5f0dd742ae27be33ded761ee78e8870fe256d2a9d3e8da64fbd8a5c544391dbd0b1633030c06c46a9f71d35a50eaba2aba07c6c17e3ffdbe4a4edace641283d2 -------------------------------------------------------------------------------- /checksum/oga-0.1.3.gem.sha512: -------------------------------------------------------------------------------- 1 | 10809682eae382fe45520d1daddef82d3219cc2b4553ba88fd1e8ff00c476e78f4e1e63e37a6026a4088a87f5f4f4d6360ae29cfd455a920ef33218300fde5d8 -------------------------------------------------------------------------------- /checksum/oga-0.2.0-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 1a4689fce15cda960ede131edc2fc3b8ce8412fd7752891ad94c49a4036f667659233fd7b3ed290c46b40d55ff184bc78fb28037d40b0a942e5533e3c37b9ce0 -------------------------------------------------------------------------------- /checksum/oga-0.2.0.gem.sha512: -------------------------------------------------------------------------------- 1 | 1ce276188693c950da61845e3b89a915da3c13022e2bb26acfb7312b7d9373f2289496b08a5f8ab340f5276d692cc8283a3a7e19eaa055f790c101b412081527 -------------------------------------------------------------------------------- /checksum/oga-0.2.1-java.gem.sha512: -------------------------------------------------------------------------------- 1 | b68fdd93c7518f01fa8122640218e6119f9071798cfb66cb61da763242d30b8892948d495f9b1d249985df96716dcf0bf7dc132141c7bd81d4ff0d7c7d45ab09 -------------------------------------------------------------------------------- /checksum/oga-0.2.1.gem.sha512: -------------------------------------------------------------------------------- 1 | e2152d2305f871cde8c33d548a30c45aae917f793c5aef3d09b50677cdbfd5e0777c381adf322cc34fd7549a6fbf4eeb1f87c45b0f3c2743c991ca9c2eb291e9 -------------------------------------------------------------------------------- /checksum/oga-0.2.2-java.gem.sha512: -------------------------------------------------------------------------------- 1 | d77f7f9891d29b8b16686e46f86b2ef5cfcc5a55b38f822352a275445a1fb77eee72b49b7f4747f67586bda6eb62e8878a3bb3011172508adf19ba3109747f7a -------------------------------------------------------------------------------- /checksum/oga-0.2.2.gem.sha512: -------------------------------------------------------------------------------- 1 | ca6c16656dd7fd2fefd1530845ee834eb882079bcdaca15382661f0e7e963a7a96d20a5cdfd4801ff5ae0cff98de35e6beb2306063776a4443d0867b9f8b8c97 -------------------------------------------------------------------------------- /checksum/oga-0.2.3-java.gem.sha512: -------------------------------------------------------------------------------- 1 | d90ddb95b292d7051bc3ae57310ecd83bd3eeabea217cde025868546d669cbdff9258fa55d9155b7e09dc728d2647775ff37b7cfc3cc56c2a098890b089f77b8 -------------------------------------------------------------------------------- /checksum/oga-0.2.3.gem.sha512: -------------------------------------------------------------------------------- 1 | 996ed94cc7049fae8d8da38e08c8154b2dae15b785fbcf1d8bed3d2860c1755492520d9a784781fa755c9b92e6efb62b9c9d6df24d36039e6e7a3e7b65e8f369 -------------------------------------------------------------------------------- /checksum/oga-0.3.0-java.gem.sha512: -------------------------------------------------------------------------------- 1 | ef5a6e5f01d9512f30b67f03bea7968f2df335f0e5faccd68c470920deaf29ba54f1777628f929821ae5863d6dcc12cde33435bcd5a94bda4c9d856ea86de46b -------------------------------------------------------------------------------- /checksum/oga-0.3.0.gem.sha512: -------------------------------------------------------------------------------- 1 | a3b6f4ba298a6209be054f1260ec1f45bb7265722876b1f67d8a4270808ab173c5796c65faf27e30aeaa88015660aad5f925fe2697fa0f1136bab9dedd938ff8 -------------------------------------------------------------------------------- /checksum/oga-0.3.1-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 45b984367535586c8a99e982d3ece841ae50ef37d58f7028265a532db2a12b0592c6e168e030456e4c8b3d6f5da984963d2246bf766e7a7efe0feb41fed45014 -------------------------------------------------------------------------------- /checksum/oga-0.3.1.gem.sha512: -------------------------------------------------------------------------------- 1 | 2c56546ff219fffc64485e290dbc27ae1211e6c79a9eb966508534fa6bb9773629ddef52b758025e0fa59e95623bdb862d18636a9f70c392451a5b81acd43e0c -------------------------------------------------------------------------------- /checksum/oga-0.3.2-java.gem.sha512: -------------------------------------------------------------------------------- 1 | dc383998714d4f8199f8b7ad9067763ff78a3a566e64cf5b3d936ff894af5689ae8e2060e9445709a996009a6342219809d2e19a2a82170f9cd2270f5100f88c -------------------------------------------------------------------------------- /checksum/oga-0.3.2.gem.sha512: -------------------------------------------------------------------------------- 1 | 08e279b83b2d79b06509d977d2a368cf5ac74524f2f0d5e7e04d444af3d56678d6c64095af87eb485c723c4f75796d95e7c82a6b842715aa4db11026f4f1ea5f -------------------------------------------------------------------------------- /checksum/oga-0.3.3-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 24cece6200e0aca5d5a5ca59631a8f154a60b2679d9a3e1cd4e488d08d3297fa2925c6c14a1ad5ca7f9a9ea0102e11f80a67b156da56ede79c73c8293be2bd9f -------------------------------------------------------------------------------- /checksum/oga-0.3.3.gem.sha512: -------------------------------------------------------------------------------- 1 | d6f36fa609fe45e160e2699d900ef573194ea5e949a6c4836cb0b150b465cf4dace74728c32da306409149b8407d7086a2ab3ba8ddfbfb3ce6e4c76139413bf9 -------------------------------------------------------------------------------- /checksum/oga-0.3.4-java.gem.sha512: -------------------------------------------------------------------------------- 1 | ab9b37bec702eddc7fa9b97e92a804fdb7937bc630bcfd786345f8ca7ba81cf3a45a8f638416ba1e51db9f7febb38cd5ac3a1bccf9276f008267bbc06f27295c -------------------------------------------------------------------------------- /checksum/oga-0.3.4.gem.sha512: -------------------------------------------------------------------------------- 1 | d8936b2981524f5b879a449919451c94b162a47678e525fafe85c17321d4ec29adaf94e96813f795804892759dbd66c8cc028ca68191f56fa17fe483b44df96e -------------------------------------------------------------------------------- /checksum/oga-1.0.0-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 257e1c86abdcadbb5fc6490d0a9bcfd0c8514a7e2f6a81e3f381f876310249595bbb0e9bb274a28c99e5b3ee1e7af8ad298e5648ccf5c880913ab8f7ba863125 -------------------------------------------------------------------------------- /checksum/oga-1.0.0.gem.sha512: -------------------------------------------------------------------------------- 1 | 9f6c49ae7811268b64ae19a4b8b3e2e9d20af1b03ad244571a484aee50d80999515aebc0bf501bf929c2879966ae1c41f06254497b46c839aea0b65c9146068a -------------------------------------------------------------------------------- /checksum/oga-1.0.1-java.gem.sha512: -------------------------------------------------------------------------------- 1 | ff8de4f94210f149ec0eee38f436f4ece68a204b8fdeb062d54275ff3237be1251e265159048ae8859bd4058e4b8a13aeb765c71b2d33ee11cde3eeed08dc6b2 -------------------------------------------------------------------------------- /checksum/oga-1.0.1.gem.sha512: -------------------------------------------------------------------------------- 1 | cddad871b652fc12c82017da7902e11513411c59cc91a55937e8bd7e7006390a46c5ef8839869e955c857039f0931bf6d2eb2b896d59c7a64314e40aa8fc5389 -------------------------------------------------------------------------------- /checksum/oga-1.0.2-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 3186afc33f26cdae216b37ce3454691f0957bba89e0c410383be8306be4834469104108aa0f47cfcc48fb256fa3773239f75445ebdd2bb802368b5174c575cc1 -------------------------------------------------------------------------------- /checksum/oga-1.0.2.gem.sha512: -------------------------------------------------------------------------------- 1 | 46d7ef4d9bb975b4df6363c5eaf3f7554bf35846068cf6e66c2f7e7a130fd19e44650333d6ba2774c4047a8e97d15373c0081d9cd461b51867c1b3429629eb7e -------------------------------------------------------------------------------- /checksum/oga-1.0.3-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 9374bb16ecd268c05c0bc4aec871c5c2e46b1bb5de5ed8f028e1a8f6370008d22980a996abd646d61feb91ce708edb0621dbb4cbfe74520c29fc273216d24aa7 -------------------------------------------------------------------------------- /checksum/oga-1.0.3.gem.sha512: -------------------------------------------------------------------------------- 1 | 854ee26216e2646f562a1bc477df8b00fac4375620993c512e2c0749c84683503671339e374c5861dcaf43534f80df4a5c791ac834c91ec9a59835be51042bf5 -------------------------------------------------------------------------------- /checksum/oga-1.1.0-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 979cabb88f8379103aa3dffc02a6cd5803a47a6ac5b122320324573907e81130bf56114d91a736fc1b0d11656d9952689db8ec2e3a7baf39ece20f28c1c7cfc3 -------------------------------------------------------------------------------- /checksum/oga-1.1.0.gem.sha512: -------------------------------------------------------------------------------- 1 | 30cd5f91b3db3b0638818136327077fed8a493918eba2438d0489489a17b1f58bd568f54c888e447a64b5a0de7ace706de08947fac817ac053ce6bb2f2096964 -------------------------------------------------------------------------------- /checksum/oga-1.2.0-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 032bd9f3d315589d17ff44ffbf1e779e306a363c9c5c8990cac9cfc419337f130dc339955530eefaf5cb9fa1e3f59fdb853f06df85fa695c2f3f6e80df3d3335 -------------------------------------------------------------------------------- /checksum/oga-1.2.0.gem.sha512: -------------------------------------------------------------------------------- 1 | 5155866d610c2e42a923aa91fc4dfe68bf15fa3b8b8068b68a40c5aedc1b9653b06fce5cf83025881ccfdb80c73777092ca1afa65df27378c76f5f37861eb796 -------------------------------------------------------------------------------- /checksum/oga-1.2.1-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 04901b4460bbe0402d0699469da7606f48d46d8208a480a0f74ace734538a9232435444500136845ccdeb612e5c6787c555726bc7070690229d7ad48336d910f -------------------------------------------------------------------------------- /checksum/oga-1.2.1.gem.sha512: -------------------------------------------------------------------------------- 1 | 7fa7e55ff0fb20baf0be8041d00fc90b602537415e6b08ada43bfc84f6a76ef7d600636cbf9bd4014c27792cfcba17c92521936ec12e7bd96a45490f0568bc3e -------------------------------------------------------------------------------- /checksum/oga-1.2.2-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 2dbf0b20adeb43f38dc57fc28d84a1364854c097efd514c2c965d055751b582a6e301bd7f3d751a0c41cd4b6abc94cb43e5110bc96fc727706cc5b9ce6f3ad53 -------------------------------------------------------------------------------- /checksum/oga-1.2.2.gem.sha512: -------------------------------------------------------------------------------- 1 | fbd1ab8dbbe4385d88cd1eb776bc781ffebde8bba30da5ef83fe62bb5eecbe16e5c83a9359e29e6b6dbe5c5f2c11607713311d80cd3e82b20a93d6e70c98457c -------------------------------------------------------------------------------- /checksum/oga-1.2.3-java.gem.sha512: -------------------------------------------------------------------------------- 1 | e47d72f74378468f19682d9cfc81ff1b319c15d56f26e85904bafda915b7997617981a0a952c7a5ec77b46014f507da38ecb4c7d73dcd8b8b20e4f3961731f45 -------------------------------------------------------------------------------- /checksum/oga-1.2.3.gem.sha512: -------------------------------------------------------------------------------- 1 | 49287b1a35a31030f4905d3c4e460b847633f7c1af8a0e2e3b6bf2097e7316fe26edce371670ea7db6ea73a74d362dd9c2fa4f19571e532e8559534f38d59f8d -------------------------------------------------------------------------------- /checksum/oga-1.3.0-java.gem.sha512: -------------------------------------------------------------------------------- 1 | fbb014fbaf1a90231da02372d8120c357385f3b8d6e85fe3d20aa5eb60b5292b8de7ef81e3f9bb4d16a0e36b5901802a07fdef4821ba7b9e2d6468051d9633fd -------------------------------------------------------------------------------- /checksum/oga-1.3.0.gem.sha512: -------------------------------------------------------------------------------- 1 | c42b8817d8a29430e2af9a610e184de9cd32f22a669f9237bcff0e8c445d71aaf8dc04b184d1eb4dc4245aef689c953b49266b1359e08774aa30edb7ff27a9a0 -------------------------------------------------------------------------------- /checksum/oga-1.3.1-java.gem.sha512: -------------------------------------------------------------------------------- 1 | cabf9a27a9f8b3b5dcc11d249df5cfaf803e87dc0a727234e8859beb0cecfa83c6e127f6ab05bbeb44de35711278d7b16ac11d7243f8d0b6aa024004d8c8b2db -------------------------------------------------------------------------------- /checksum/oga-1.3.1.gem.sha512: -------------------------------------------------------------------------------- 1 | 59f18e92426f057671d3ac30931632284f1aa0fcd3bea5c1a78928fe2ded93d58ac15d57ae335dd7dbc384b8f74d32bd7bb1790ba3c65912d5f85cd6fb5e75e4 -------------------------------------------------------------------------------- /checksum/oga-2.0.0-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 040fe3d53c5386f578d7cd6b1be4931c05d9c6d7ff42b89ddb3936771c2d68e028ecd31449e6a448be475fc06afa210b3bb3256e4b58a9c35bb49318f905623f -------------------------------------------------------------------------------- /checksum/oga-2.0.0.gem.sha512: -------------------------------------------------------------------------------- 1 | 3ace7512c849c62e8c6506778adb7151cf6a518e8ed76330caacbf2359791ed46cd9d6660ff57ad3060b50642bce5429d7c3f2063a6b1cf21b8cdc0e7d83e87f -------------------------------------------------------------------------------- /checksum/oga-2.1-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 78723c9b6622658b2c26c258fe7a061b8d14839b263003314dfb16a6fb5c94493c75b7a41d308e7fe9020485afde7cbe5e5c6c39acc5de6e36f615a128857cbf -------------------------------------------------------------------------------- /checksum/oga-2.1.gem.sha512: -------------------------------------------------------------------------------- 1 | a8e366ddb1dd889862c696399e558c77341ec190cceaf946f37a92802f028c5779006f6f120e343a1a6b3498174718cb1473aa45d20ad844f90f46ca05f3ee3b -------------------------------------------------------------------------------- /checksum/oga-2.10-java.gem.sha512: -------------------------------------------------------------------------------- 1 | bac38b7526a1c7460175933942f9c6e7655807b5250c7032b2be8633f1d616a9285084a57e1ee3a4b6a05d15ae1490b09313a827f85fd8ebcb46a7c65d2175c0 -------------------------------------------------------------------------------- /checksum/oga-2.10.gem.sha512: -------------------------------------------------------------------------------- 1 | 84f6fe917bf8e335b391f0817cab9fb07b8c9ad2c3618ce530b3443d0c6e8e31f47cccc039f376a1b3d329a5cc0d3a84664f3e72a7c85b31b5b02b6db5c8360f -------------------------------------------------------------------------------- /checksum/oga-2.11-java.gem.sha512: -------------------------------------------------------------------------------- 1 | e89ef454241cad99049fa3767eb1c76ab7e1e10a0943e6448ffc7cfc70a251f7a72a3cd61f0664c35a54791752960b6432ddd857d56d11594b6272bff44d405b -------------------------------------------------------------------------------- /checksum/oga-2.11.gem.sha512: -------------------------------------------------------------------------------- 1 | d6d3f1f133c9f93bd9cc36b7748c5b8a223d53daacb0ed0c9784fb0aac08d483c558208ddda1fc6b7b544a638a4cd89f791d397c712f622b7096d0b99ab7ec79 -------------------------------------------------------------------------------- /checksum/oga-2.12-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 5389228f4c92851e74396e507c37b0fbe8659522fad0932954a710640268cd51926185b0d4c7887b6d5c13f11af0dbde45fb43d0dd1adce5d8688f050d2de1ed -------------------------------------------------------------------------------- /checksum/oga-2.12.gem.sha512: -------------------------------------------------------------------------------- 1 | ab7a64c63bf2f03ecfe42f45199c943d60240eed0ee57f71e1d05fe8d29264c942f12bba8c34d3e3c22f4cb502611d3c65bda17a8c4afec9a593599537c143b6 -------------------------------------------------------------------------------- /checksum/oga-2.13-java.gem.sha512: -------------------------------------------------------------------------------- 1 | a5492d3bfb21fad9060412e4189b2f08c179840eae5bacee2580795e5ce6bf9aa10d7e95c1e7729259c708f25051cf4df7d48261a05fbda8c39c5879656135c9 -------------------------------------------------------------------------------- /checksum/oga-2.13.gem.sha512: -------------------------------------------------------------------------------- 1 | 5acda689eff5c8f6ac03f97189f9906305576ab213276f317e5136476751905a0748be7058eca808d80bbdbe50475024c40400c135946c56fd2e0b958a8b4037 -------------------------------------------------------------------------------- /checksum/oga-2.14-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 565cc42a3d776ead3bae1423af8b24279ef53f4ebdee7812bd2c842cf5660f0f6a8ac0054ed9dee37493f42335e0ab529c5aae965e218e49201c9408358ddb4c -------------------------------------------------------------------------------- /checksum/oga-2.14.gem.sha512: -------------------------------------------------------------------------------- 1 | 05cb13515c8b4e99b0c59fb7d362b7245ad97eb4a9243c6a4c9eb8c89bd2a1db19b6951a7cd6e7484493df31aa49b8e0ce64c1aa15ecd3dafd4aa6fc5578918b -------------------------------------------------------------------------------- /checksum/oga-2.15-java.gem.sha512: -------------------------------------------------------------------------------- 1 | beaa3a5d8c5b64288f83f141daece073b3601ff631dc33a4a7d268fcf38b5a667c44c3ed67964baa6e250501b3b965df3b6ecfeee9a407a063981e91474baef9 -------------------------------------------------------------------------------- /checksum/oga-2.15.gem.sha512: -------------------------------------------------------------------------------- 1 | b5071a0cd5d2d1bf79577ed1235ac9233de5cbbffc5c47a5ba375152dbf11fc6f1c8c66253d986288817862915df350aad7a7760ec8c536b479c9d5850a34cbf -------------------------------------------------------------------------------- /checksum/oga-2.16-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 241e4861fb8cdb8576b72672a2ad1d59e0f72333eb203d19b8922e15091a3470d0150d417f78d2394e2c9140fa7c9d87508acc51907537f57813b8c23272922e -------------------------------------------------------------------------------- /checksum/oga-2.16.gem.sha512: -------------------------------------------------------------------------------- 1 | 5a2abc35e0696adf408f1d517865e49d511b26e39c0fe6a1f299baf77563327661498f3e1d70e20feb118810eb6457649706dc4fc3e8c45868d4b3d0ef56bfc8 -------------------------------------------------------------------------------- /checksum/oga-2.17-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 4e35c653ef64ebfbbee7a933923e9cf53e988028e53cb1535127962d249501881ce35e5c7375b98e43e220b7561961a9d35fe15caf20b263b20367660a59b3eb -------------------------------------------------------------------------------- /checksum/oga-2.17.gem.sha512: -------------------------------------------------------------------------------- 1 | 9cbb14e1abea3ebec3b7e9051bff5cae466cc4e608df6aa7826add38bcdb5b406cc8090405e63128a6902b24a64082ef5b9d1a36970c399ef4c941f63f2ee305 -------------------------------------------------------------------------------- /checksum/oga-2.2-java.gem.sha512: -------------------------------------------------------------------------------- 1 | ccc4f79b4b0a6041f1d8fbc6468655769ef207889e32cba9fddccf512fab524b5017d97a1290e3b8016b1911cde65febe9255edee72dd01a5f41077790f09701 -------------------------------------------------------------------------------- /checksum/oga-2.2.gem.sha512: -------------------------------------------------------------------------------- 1 | 4a81fb7280e68714ab2c1a24282c9204c088a0aa8938ae2101ee5493604e5298204a6bb275c620a1fb4c2824001b2f31348b9ca019629ba4de5fbaa65a123994 -------------------------------------------------------------------------------- /checksum/oga-2.3-java.gem.sha512: -------------------------------------------------------------------------------- 1 | c8d3fad8132061c0d1650c1320b382e4ef81669e9db61a61127ae0f364c08c413e644c57207b94f1c0a671600aac193739b56861c60ce68f88866837c193b55d -------------------------------------------------------------------------------- /checksum/oga-2.3.gem.sha512: -------------------------------------------------------------------------------- 1 | 1ee2b613c6c39228fadea98c073a1b31487e9dc2aa29c99c2b5221749fcf7cf99f933cb4a5f03b336d4fa8aca006ace10f6d4ff0156a109866265065ae776aa7 -------------------------------------------------------------------------------- /checksum/oga-2.4-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 723d87b4c8cecdf3f0edfbac5e72411f5abea90d90a3a2269e24823424251da1a2378399c17ab69e0eb28957731b3c7f075026caccb71ce8907505baebeea0f4 -------------------------------------------------------------------------------- /checksum/oga-2.4.gem.sha512: -------------------------------------------------------------------------------- 1 | d8ff0a1d96b217f09d010173dd97b0036692098ebe5c33385618c2fd542e63c01a3990f9a74beea139c49f8ee3692427899748125249469c19633fae38b9beb3 -------------------------------------------------------------------------------- /checksum/oga-2.5-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 885d4a6155a93d50bff733c778886feb1a514ccf4bd937eabd022439622c75b83b00bd9994c974c9733e97f38b6dd02d882dc994868ca7bb90f03133cad70255 -------------------------------------------------------------------------------- /checksum/oga-2.5.gem.sha512: -------------------------------------------------------------------------------- 1 | c129448eeabb128fd223833197efeb057fb03ccd33434c897bb5e27ceceee0a32cfd6f8abe2a7ab8512c0edadad99cedc994332262cf569a623eea9fc0287473 -------------------------------------------------------------------------------- /checksum/oga-2.6-java.gem.sha512: -------------------------------------------------------------------------------- 1 | b107dec6aff28640a307ca02661abd5a29a5f0c369422c116bad7a198b11eb9aa9cab90bfe874a0c9fd4391343d4b5589fcbf5b5a0ff557ab520fd83725de9e8 -------------------------------------------------------------------------------- /checksum/oga-2.6.gem.sha512: -------------------------------------------------------------------------------- 1 | 8c888218a3da5a639df19e042a3e66bea2d5eec5c660bb4f13982eaff0626f80ab2840d0f58bba2a1fe5dce12563b5f73a9f7b15f23b05ff5c87fe4b7f064621 -------------------------------------------------------------------------------- /checksum/oga-2.7-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 9bfe28b9b7b971fd80f405ad12c7c58cc94152b85ed29d4dc1e50525d220e1bc0a42fa76083fc0637a8c799f31c2c3599664df68af3dd2ed2c8ed3ae20b5b6a2 -------------------------------------------------------------------------------- /checksum/oga-2.7.gem.sha512: -------------------------------------------------------------------------------- 1 | 1a00cd24864ce2777a02f2c1964ca636654d860e61a0be7437bdcc8bf1afe393138ced1913117eb58ac10bd25f306fda16e0ae2f737486414522102642ac03e5 -------------------------------------------------------------------------------- /checksum/oga-2.8-java.gem.sha512: -------------------------------------------------------------------------------- 1 | e948ef42c95ca8c0a8b1fe7f765c75b2be048ccd154cdafd49610e7c80c44a7592152bdc02cb37f466b62be99299b20879392518c98d4f94a0bad121d5844c44 -------------------------------------------------------------------------------- /checksum/oga-2.8.gem.sha512: -------------------------------------------------------------------------------- 1 | 59f3805163a97f3b06c13c9c46691bb34c106a4cdac3d04f57aaf93c64de74016b9485eff81d9461f21162887d1f114e6fa22bcfc0c36eb57d4ca93716ff001f -------------------------------------------------------------------------------- /checksum/oga-2.9-java.gem.sha512: -------------------------------------------------------------------------------- 1 | 2839f9bf005a0875d87d0b6796aab4c4e6591ff1a02e8032ce9bc06d340db9fde3ac32d79f8ae19c9fd7cac8a4b3c50a9a5840b72e7912f205dfd12320466c41 -------------------------------------------------------------------------------- /checksum/oga-2.9.gem.sha512: -------------------------------------------------------------------------------- 1 | c60b30f7b83b21916ed54ce37d5bed734f7e5807576ce2fb94e5ac577a479fa5a9f19594d44587b635727c6c9f88d0fc75c945d22f32342df6e159878b2c950d -------------------------------------------------------------------------------- /checksum/oga-3.0-java.gem.sha512: -------------------------------------------------------------------------------- 1 | b64906a38edefb346c2ba9770336cb69f424e0776690932fea524f014dda00d8fe1b13b69fff1f01ca75c8f5107b92056c25f8ae7ee4aeb83770dc03b5d482c0 -------------------------------------------------------------------------------- /checksum/oga-3.0.gem.sha512: -------------------------------------------------------------------------------- 1 | 56eea6f76968afb2916e73d729a9c94dcacfb1cccc6fa0ef27888e6e8006a80cda9279db4b040be81b33ee354916e49e437ce0189ce79bdbab7c0f54203b9f2e -------------------------------------------------------------------------------- /checksum/oga-3.1-java.gem.sha512: -------------------------------------------------------------------------------- 1 | a2246547f87d1901e280d9df915bf41a6b78ac14805c5c0f471f5dd1cf617f1e5b3e4aa05e58ae5aa816e188456ccd3638e44a7aba41ed2dfb942f509b2093af -------------------------------------------------------------------------------- /checksum/oga-3.1.gem.sha512: -------------------------------------------------------------------------------- 1 | deb03862d5263b2cb47169267aa37c41be82fcb01d048d840506d2c8924fb0bba6a4407401052e8a5f42d053c2bb3410701316fe21570b35a2981850dc05a481 -------------------------------------------------------------------------------- /checksum/oga-3.2-java.gem.sha512: -------------------------------------------------------------------------------- 1 | b0c3740f08d33f5b9a76c6532de749b8004fb591e3bd3b745e8c57a3bbc5b3d6be4c9a02432fc32f4ae3ca53b488dc409243af91e43646ba3f486fec4738911e -------------------------------------------------------------------------------- /checksum/oga-3.2.gem.sha512: -------------------------------------------------------------------------------- 1 | 27f941862134b9e5fc46b33d8dd642a7c816f8b0bb6448789c5f23e9da42abdc72b19713985cf81257074931a4f51e014aa551e09bcb7858cde9987ea17aca75 -------------------------------------------------------------------------------- /checksum/oga-3.3-java.gem.sha512: -------------------------------------------------------------------------------- 1 | c5521d5bc9e025fadfb4e0719c8ff0fa103dd7c184cdf4c60154a1bb5f7d71c9d807a84e76a21b13665de1bbe54f9ba23f6e479650b1bd497302f86ff2af8bbf -------------------------------------------------------------------------------- /checksum/oga-3.3.gem.sha512: -------------------------------------------------------------------------------- 1 | be44f4fb2f5f821306556b965a928e42753a57e489516654bdda74662058510cdc9885b50f6170f23762309f3a7c94791d8db71180272961341c917ffc3560e4 -------------------------------------------------------------------------------- /checksum/oga-3.4-java.gem.sha512: -------------------------------------------------------------------------------- 1 | eef134163a86451be4a5ec72b262fec6a1dad10613e0d4002142b09e02cb444cc25ce018cdd62a870b266fc8dd390ba4fe110e07a2c41f50a3d8abdcc69b5dec -------------------------------------------------------------------------------- /checksum/oga-3.4.gem.sha512: -------------------------------------------------------------------------------- 1 | 2ba0fdbfa3fa15b8d1ce5df4df4cfb3813f34399c93517f98ec8da1e82ff3cdc6e3543bf017b8246daa8b2521a64af92a9438a404b69da0f319272c510961314 -------------------------------------------------------------------------------- /doc/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yorickpeterse/oga/6c4356f0f5af0212e9c6043b45b660b61fc624b4/doc/.gitkeep -------------------------------------------------------------------------------- /doc/css/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yorickpeterse/oga/6c4356f0f5af0212e9c6043b45b660b61fc624b4/doc/css/.gitkeep -------------------------------------------------------------------------------- /doc/css/common.css: -------------------------------------------------------------------------------- 1 | body 2 | { 3 | font-size: 14px; 4 | line-height: 1.6; 5 | } 6 | 7 | p code, dd code, li code 8 | { 9 | background: #f9f2f4; 10 | color: #c7254e; 11 | border-radius: 4px; 12 | padding: 2px 4px; 13 | } 14 | 15 | pre.code 16 | { 17 | font-size: 13px; 18 | line-height: 1.4; 19 | overflow: auto; 20 | } 21 | 22 | blockquote 23 | { 24 | border-left: 5px solid #eee; 25 | margin: 0px; 26 | padding-left: 15px; 27 | } 28 | 29 | /** 30 | * YARD uses generic table styles, using a special class means those tables 31 | * don't get messed up. 32 | */ 33 | .table 34 | { 35 | border: 1px solid #ccc; 36 | border-right: none; 37 | border-collapse: separate; 38 | border-spacing: 0; 39 | text-align: left; 40 | } 41 | 42 | .table.full 43 | { 44 | width: 100%; 45 | } 46 | 47 | .table .field_name 48 | { 49 | min-width: 160px; 50 | } 51 | 52 | .table thead tr th.no_sort:first-child 53 | { 54 | width: 25px; 55 | } 56 | 57 | .table thead tr th, .table tbody tr td 58 | { 59 | border-bottom: 1px solid #ccc; 60 | border-right: 1px solid #ccc; 61 | min-width: 20px; 62 | padding: 8px 5px; 63 | text-align: left; 64 | vertical-align: top; 65 | } 66 | 67 | .table tbody tr:last-child td 68 | { 69 | border-bottom: none; 70 | } 71 | 72 | .table tr:nth-child(odd) td 73 | { 74 | background: #f9f9f9; 75 | } 76 | -------------------------------------------------------------------------------- /ext/c/extconf.rb: -------------------------------------------------------------------------------- 1 | require 'mkmf' 2 | 3 | if RbConfig::CONFIG['CC'] =~ /clang|gcc/ 4 | $CFLAGS << ' -pedantic -Wno-implicit-fallthrough' 5 | end 6 | 7 | if ENV['DEBUG'] 8 | $CFLAGS << ' -O0 -g' 9 | end 10 | 11 | create_makefile('liboga') 12 | -------------------------------------------------------------------------------- /ext/c/lexer.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBOGA_XML_LEXER_H 2 | #define LIBOGA_XML_LEXER_H 3 | 4 | #include "liboga.h" 5 | 6 | extern void Init_liboga_xml_lexer(); 7 | 8 | typedef struct { 9 | int act; 10 | int cs; 11 | int lines; 12 | int stack[4]; 13 | int top; 14 | } OgaLexerState; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /ext/c/liboga.c: -------------------------------------------------------------------------------- 1 | #include "liboga.h" 2 | 3 | void Init_liboga() 4 | { 5 | Init_liboga_xml_lexer(); 6 | } 7 | -------------------------------------------------------------------------------- /ext/c/liboga.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBOGA_H 2 | #define LIBOGA_H 3 | 4 | #include 5 | #include 6 | 7 | #include "lexer.h" 8 | 9 | void Init_liboga(); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /ext/java/Liboga.java: -------------------------------------------------------------------------------- 1 | package org.liboga; 2 | 3 | import org.jruby.Ruby; 4 | 5 | public class Liboga 6 | { 7 | /** 8 | * Bootstraps the JRuby extension. 9 | */ 10 | public static void load(final Ruby runtime) 11 | { 12 | org.liboga.xml.Lexer.load(runtime); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/oga/blacklist.rb: -------------------------------------------------------------------------------- 1 | module Oga 2 | # @api private 3 | class Blacklist 4 | # @return [Set] 5 | attr_reader :names 6 | 7 | # @param [Array] names 8 | def initialize(names) 9 | @names = Set.new(names + names.map(&:upcase)) 10 | end 11 | 12 | # @yieldparam [String] 13 | def each 14 | names.each do |value| 15 | yield value 16 | end 17 | end 18 | 19 | # @return [TrueClass|FalseClass] 20 | def allow?(name) 21 | !names.include?(name) 22 | end 23 | 24 | # @param [Oga::Blacklist] other 25 | # @return [Oga::Blacklist] 26 | def +(other) 27 | self.class.new(names + other.names) 28 | end 29 | end # Blacklist 30 | end # Oga 31 | -------------------------------------------------------------------------------- /lib/oga/entity_decoder.rb: -------------------------------------------------------------------------------- 1 | module Oga 2 | module EntityDecoder 3 | # @see [decode] 4 | def self.try_decode(input, html = false) 5 | input ? decode(input, html) : nil 6 | end 7 | 8 | # @param [String] input 9 | # @param [TrueClass|FalseClass] html 10 | # @return [String] 11 | def self.decode(input, html = false) 12 | decoder = html ? HTML::Entities : XML::Entities 13 | 14 | decoder.decode(input) 15 | end 16 | end # EntityDecoder 17 | end # Oga 18 | -------------------------------------------------------------------------------- /lib/oga/html/parser.rb: -------------------------------------------------------------------------------- 1 | module Oga 2 | module HTML 3 | # Parser for processing HTML input. This parser is a small wrapper around 4 | # {Oga::XML::Parser} and takes care of setting the various options required 5 | # for parsing HTML documents. 6 | # 7 | # A basic example: 8 | # 9 | # Oga::HTML::Parser.new('').parse 10 | class Parser < XML::Parser 11 | # @param [String|IO] data 12 | # @param [Hash] options 13 | # @see [Oga::XML::Parser#initialize] 14 | def initialize(data, options = {}) 15 | options = options.merge(:html => true) 16 | 17 | super(data, options) 18 | end 19 | end # Parser 20 | end # HTML 21 | end # Oga 22 | -------------------------------------------------------------------------------- /lib/oga/html/sax_parser.rb: -------------------------------------------------------------------------------- 1 | module Oga 2 | module HTML 3 | # SAX parser for HTML documents. See the documentation of 4 | # {Oga::XML::SaxParser} for more information. 5 | class SaxParser < XML::SaxParser 6 | # @see [Oga::XML::SaxParser#initialize] 7 | def initialize(handler, data, options = {}) 8 | options = options.merge(:html => true) 9 | 10 | super(handler, data, options) 11 | end 12 | end # SaxParser 13 | end # HTML 14 | end # Oga 15 | -------------------------------------------------------------------------------- /lib/oga/oga.rb: -------------------------------------------------------------------------------- 1 | module Oga 2 | # Parses the given XML document. 3 | # 4 | # @example 5 | # document = Oga.parse_xml('Hello') 6 | # 7 | # @see [Oga::XML::Lexer#initialize] 8 | # 9 | # @return [Oga::XML::Document] 10 | def self.parse_xml(xml, options = {}) 11 | XML::Parser.new(xml, options).parse 12 | end 13 | 14 | # Parses the given HTML document. 15 | # 16 | # @example 17 | # document = Oga.parse_html('...') 18 | # 19 | # @see [Oga::XML::Lexer#initialize] 20 | # 21 | # @return [Oga::XML::Document] 22 | def self.parse_html(html, options = {}) 23 | HTML::Parser.new(html, options).parse 24 | end 25 | 26 | # Parses the given XML document using the SAX parser. 27 | # 28 | # @example 29 | # handler = SomeSaxHandler.new 30 | # 31 | # Oga.sax_parse_html(handler, 'Hello') 32 | # 33 | # @see [Oga::XML::SaxParser#initialize] 34 | def self.sax_parse_xml(handler, xml, options = {}) 35 | XML::SaxParser.new(handler, xml, options).parse 36 | end 37 | 38 | # Parses the given HTML document using the SAX parser. 39 | # 40 | # @example 41 | # handler = SomeSaxHandler.new 42 | # 43 | # Oga.sax_parse_html(handler, '') 44 | # 45 | # @see [Oga::XML::SaxParser#initialize] 46 | def self.sax_parse_html(handler, html, options = {}) 47 | HTML::SaxParser.new(handler, html, options).parse 48 | end 49 | end # Oga 50 | -------------------------------------------------------------------------------- /lib/oga/version.rb: -------------------------------------------------------------------------------- 1 | module Oga 2 | VERSION = '3.4' 3 | end # Oga 4 | -------------------------------------------------------------------------------- /lib/oga/whitelist.rb: -------------------------------------------------------------------------------- 1 | module Oga 2 | # @api private 3 | class Whitelist < Blacklist 4 | # @return [TrueClass|FalseClass] 5 | def allow?(name) 6 | names.include?(name) 7 | end 8 | 9 | # @return [Oga::Blacklist] 10 | def to_blacklist 11 | Blacklist.new(names) 12 | end 13 | end # Whitelist 14 | end # Oga 15 | -------------------------------------------------------------------------------- /lib/oga/xml/cdata.rb: -------------------------------------------------------------------------------- 1 | module Oga 2 | module XML 3 | # Class used for storing information about CDATA tags. 4 | class Cdata < CharacterNode 5 | end # Cdata 6 | end # XML 7 | end # Oga 8 | -------------------------------------------------------------------------------- /lib/oga/xml/character_node.rb: -------------------------------------------------------------------------------- 1 | module Oga 2 | module XML 3 | # Base class for nodes that represent a text-like value such as Text and 4 | # Comment nodes. 5 | class CharacterNode < Node 6 | # @return [String] 7 | attr_accessor :text 8 | 9 | # @param [Hash] options 10 | # 11 | # @option options [String] :text The text of the node. 12 | def initialize(options = {}) 13 | super 14 | 15 | @text = options[:text] 16 | end 17 | 18 | # @return [String] 19 | def inspect 20 | "#{self.class.to_s.split('::').last}(#{text.inspect})" 21 | end 22 | end # CharacterNode 23 | end # XML 24 | end # Oga 25 | -------------------------------------------------------------------------------- /lib/oga/xml/comment.rb: -------------------------------------------------------------------------------- 1 | module Oga 2 | module XML 3 | # Class used for storing information about XML comments. 4 | class Comment < CharacterNode 5 | end # Comment 6 | end # XML 7 | end # Oga 8 | -------------------------------------------------------------------------------- /lib/oga/xml/default_namespace.rb: -------------------------------------------------------------------------------- 1 | module Oga 2 | module XML 3 | # The default XML namespace. 4 | # 5 | # @return [Oga::XML::Namespace] 6 | DEFAULT_NAMESPACE = Namespace.new( 7 | :name => 'xmlns', 8 | :uri => 'http://www.w3.org/XML/1998/namespace' 9 | ).freeze 10 | end # XML 11 | end # Oga 12 | -------------------------------------------------------------------------------- /lib/oga/xml/expanded_name.rb: -------------------------------------------------------------------------------- 1 | module Oga 2 | module XML 3 | module ExpandedName 4 | # Returns the expanded name of the current Element or Attribute. 5 | # 6 | # @return [String] 7 | def expanded_name 8 | namespace_name ? "#{namespace_name}:#{name}" : name 9 | end 10 | end # ExpandedName 11 | end # XML 12 | end # Oga 13 | -------------------------------------------------------------------------------- /lib/oga/xml/html_void_elements.rb: -------------------------------------------------------------------------------- 1 | module Oga 2 | module XML 3 | # Names of the HTML void elements that should be handled when HTML lexing 4 | # is enabled. 5 | # 6 | # @api private 7 | # @return [Oga::Whitelist] 8 | HTML_VOID_ELEMENTS = Whitelist.new(%w{ 9 | area base br col command embed hr img input keygen link meta param source 10 | track wbr 11 | }) 12 | end # XML 13 | end # Oga 14 | -------------------------------------------------------------------------------- /lib/oga/xml/namespace.rb: -------------------------------------------------------------------------------- 1 | module Oga 2 | module XML 3 | # The Namespace class contains information about XML namespaces such as the 4 | # name and URI. 5 | class Namespace 6 | # @return [String] 7 | attr_accessor :name 8 | 9 | # @return [String] 10 | attr_accessor :uri 11 | 12 | # @param [Hash] options 13 | # 14 | # @option options [String] :name 15 | # @option options [String] :uri 16 | def initialize(options = {}) 17 | @name = options[:name] 18 | @uri = options[:uri] 19 | end 20 | 21 | # @return [String] 22 | def to_s 23 | name.to_s 24 | end 25 | 26 | # @return [String] 27 | def inspect 28 | "Namespace(name: #{name.inspect} uri: #{uri.inspect})" 29 | end 30 | 31 | # @param [Oga::XML::Namespace] other 32 | # @return [TrueClass|FalseClass] 33 | def ==(other) 34 | other.is_a?(self.class) && name == other.name && uri == other.uri 35 | end 36 | end # Namespace 37 | end # XML 38 | end # Oga 39 | -------------------------------------------------------------------------------- /lib/oga/xml/processing_instruction.rb: -------------------------------------------------------------------------------- 1 | module Oga 2 | module XML 3 | # Class used for storing information about a single processing instruction. 4 | class ProcessingInstruction < CharacterNode 5 | # @return [String] 6 | attr_accessor :name 7 | 8 | # @param [Hash] options 9 | # 10 | # @option options [String] :name The name of the instruction. 11 | # @see [Oga::XML::CharacterNode#initialize] 12 | def initialize(options = {}) 13 | super 14 | 15 | @name = options[:name] 16 | end 17 | 18 | # @return [String] 19 | def inspect 20 | "ProcessingInstruction(name: #{name.inspect} text: #{text.inspect})" 21 | end 22 | end # ProcessingInstruction 23 | end # XML 24 | end # Oga 25 | -------------------------------------------------------------------------------- /lib/oga/xml/text.rb: -------------------------------------------------------------------------------- 1 | module Oga 2 | module XML 3 | # Class containing information about a single text node. Text nodes don't 4 | # have any children, attributes and the likes; just text. 5 | class Text < CharacterNode 6 | def initialize(*args) 7 | super 8 | 9 | @decoded = false 10 | end 11 | 12 | # @param [String] value 13 | def text=(value) 14 | @decoded = false 15 | @text = value 16 | end 17 | 18 | # Returns the text as a String. Upon the first call any XML/HTML entities 19 | # are decoded. 20 | # 21 | # @return [String] 22 | def text 23 | if decode_entities? 24 | @text = EntityDecoder.try_decode(@text, html?) 25 | @decoded = true 26 | end 27 | 28 | @text 29 | end 30 | 31 | # @return [TrueClass|FalseClass] 32 | def decode_entities? 33 | !@decoded && !inside_literal_html? 34 | end 35 | 36 | # @return [TrueClass|FalseClass] 37 | def inside_literal_html? 38 | node = parent 39 | 40 | node && html? && node.literal_html_name? 41 | end 42 | end # Text 43 | end # XML 44 | end # Oga 45 | -------------------------------------------------------------------------------- /lib/oga/xml/to_xml.rb: -------------------------------------------------------------------------------- 1 | module Oga 2 | module XML 3 | # Module that provides a `#to_xml` method that serialises the current node 4 | # back to XML. 5 | module ToXML 6 | # @return [String] 7 | def to_xml 8 | Generator.new(self).to_xml 9 | end 10 | 11 | alias_method :to_s, :to_xml 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/oga/xml/traversal.rb: -------------------------------------------------------------------------------- 1 | module Oga 2 | module XML 3 | # Module that provides methods to traverse DOM trees. 4 | module Traversal 5 | # Traverses through the node and yields every child node to the supplied 6 | # block. 7 | # 8 | # The block's body can also determine whether or not to traverse child 9 | # nodes. Preventing a node's children from being traversed can be done by 10 | # using `throw :skip_children` 11 | # 12 | # This method uses a combination of breadth-first and depth-first 13 | # traversal to traverse the entire XML tree in document order. See 14 | # http://en.wikipedia.org/wiki/Breadth-first_search for more information. 15 | # 16 | # @example 17 | # document.each_node do |node| 18 | # p node.class 19 | # end 20 | # 21 | # @example Skipping the children of a certain node 22 | # document.each_node do |node| 23 | # if node.is_a?(Oga::XML::Element) and node.name == 'book' 24 | # throw :skip_children 25 | # end 26 | # end 27 | # 28 | # @yieldparam [Oga::XML::Node] The current node. 29 | def each_node 30 | return to_enum(:each_node) unless block_given? 31 | 32 | visit = children.to_a.reverse 33 | 34 | until visit.empty? 35 | current = visit.pop 36 | 37 | catch :skip_children do 38 | yield current 39 | 40 | current.children.to_a.reverse_each do |child| 41 | visit << child 42 | end 43 | end 44 | end 45 | end 46 | end # Traversal 47 | end # XML 48 | end # Oga 49 | -------------------------------------------------------------------------------- /lib/oga/xml/xml_declaration.rb: -------------------------------------------------------------------------------- 1 | module Oga 2 | module XML 3 | # Class containing information about an XML declaration tag. 4 | class XmlDeclaration < ProcessingInstruction 5 | # @return [String] 6 | attr_accessor :version 7 | 8 | # @return [String] 9 | attr_accessor :encoding 10 | 11 | # Whether or not the document is a standalone document. 12 | # @return [String] 13 | attr_accessor :standalone 14 | 15 | # @param [Hash] options 16 | # 17 | # @option options [String] :version 18 | # @option options [String] :encoding 19 | # @option options [String] :standalone 20 | def initialize(options = {}) 21 | super 22 | 23 | @version = options[:version] || '1.0' 24 | @encoding = options[:encoding] || 'UTF-8' 25 | @standalone = options[:standalone] 26 | @name = 'xml' 27 | end 28 | 29 | # @return [String] 30 | def inspect 31 | segments = [] 32 | 33 | [:version, :encoding, :standalone].each do |attr| 34 | value = send(attr) 35 | 36 | if value and !value.empty? 37 | segments << "#{attr}: #{value.inspect}" 38 | end 39 | end 40 | 41 | "XmlDeclaration(#{segments.join(' ')})" 42 | end 43 | end # XmlDeclaration 44 | end # XML 45 | end # Oga 46 | -------------------------------------------------------------------------------- /lib/oga/xpath/context.rb: -------------------------------------------------------------------------------- 1 | module Oga 2 | module XPath 3 | # Class used as the context for compiled XPath Procs. 4 | # 5 | # The binding of this class is used for the binding of Procs compiled by 6 | # {Compiler}. Not using a specific binding would result in the procs 7 | # using the binding of {Compiler#compile}, which could lead to race 8 | # conditions. 9 | class Context 10 | # @param [String] string 11 | # @return [Proc] 12 | def evaluate(string) 13 | binding.eval(string) 14 | end 15 | end # Context 16 | end # XPath 17 | end # Oga 18 | -------------------------------------------------------------------------------- /oga.gemspec: -------------------------------------------------------------------------------- 1 | require File.expand_path('../lib/oga/version', __FILE__) 2 | 3 | Gem::Specification.new do |s| 4 | s.name = 'oga' 5 | s.version = Oga::VERSION 6 | s.authors = ['Yorick Peterse'] 7 | s.email = 'yorickpeterse@gmail.com' 8 | s.summary = 'Oga is an XML/HTML parser written in Ruby.' 9 | s.homepage = 'https://github.com/yorickpeterse/oga/' 10 | s.description = s.summary 11 | s.license = 'MPL-2.0' 12 | 13 | s.files = Dir.glob([ 14 | 'checkum/**/*', 15 | 'doc/**/*', 16 | 'lib/**/*.rb', 17 | 'ext/**/*', 18 | 'README.md', 19 | 'LICENSE', 20 | 'oga.gemspec', 21 | '.yardopts' 22 | ]).select { |path| File.file?(path) } 23 | 24 | if RUBY_PLATFORM == 'java' 25 | s.files << 'lib/liboga.jar' 26 | 27 | s.platform = 'java' 28 | else 29 | s.extensions = ['ext/c/extconf.rb'] 30 | end 31 | 32 | s.required_ruby_version = '>= 2.3.0' 33 | 34 | s.add_dependency 'ast' 35 | s.add_dependency 'ruby-ll', '~> 2.1' 36 | 37 | s.add_development_dependency 'rake' 38 | s.add_development_dependency 'rspec', ['~> 3.0'] 39 | s.add_development_dependency 'yard' 40 | s.add_development_dependency 'simplecov' 41 | s.add_development_dependency 'kramdown' 42 | s.add_development_dependency 'benchmark-ips', ['~> 2.0'] 43 | s.add_development_dependency 'rake-compiler' 44 | end 45 | -------------------------------------------------------------------------------- /profile/gnuplot/memory_time.gpi: -------------------------------------------------------------------------------- 1 | # The `sample_file` variable should contain the path to the variable to plot. 2 | 3 | set title sample_file 4 | 5 | set xlabel "Runtime (seconds)" 6 | set ylabel "Memory (MB)" 7 | 8 | set xtics 2 9 | 10 | set term wx persist size 1024,760 11 | set grid 12 | 13 | set style line 1 lc rgb "#0060ad" lt 1 lw 2 pt 7 ps 1 14 | set style data linespoints 15 | 16 | plot sample_file using 1:($2 / 1024 ** 2) ls 1 title "Memory" 17 | -------------------------------------------------------------------------------- /profile/plot.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | sample_file="$1" 4 | plot_script="$2" 5 | 6 | if [[ ! -f "$sample_file" ]] 7 | then 8 | echo "The sample file ${sample_file} does not exist" 9 | exit 1 10 | fi 11 | 12 | if [[ -z "$plot_script" ]] 13 | then 14 | plot_script="profile/gnuplot/memory_time.gpi" 15 | fi 16 | 17 | if [[ ! -f "$plot_script" ]] 18 | then 19 | echo "The gnuplot script ${plot_script} does not exist" 20 | exit 1 21 | fi 22 | 23 | gnuplot -e "sample_file='${sample_file}'" "${plot_script}" 24 | -------------------------------------------------------------------------------- /profile/samples/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yorickpeterse/oga/6c4356f0f5af0212e9c6043b45b660b61fc624b4/profile/samples/.gitkeep -------------------------------------------------------------------------------- /profile/samples/xml/lexer/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yorickpeterse/oga/6c4356f0f5af0212e9c6043b45b660b61fc624b4/profile/samples/xml/lexer/.gitkeep -------------------------------------------------------------------------------- /profile/samples/xml/parser/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yorickpeterse/oga/6c4356f0f5af0212e9c6043b45b660b61fc624b4/profile/samples/xml/parser/.gitkeep -------------------------------------------------------------------------------- /profile/samples/xml/pull_parser/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yorickpeterse/oga/6c4356f0f5af0212e9c6043b45b660b61fc624b4/profile/samples/xml/pull_parser/.gitkeep -------------------------------------------------------------------------------- /profile/xml/lexer/big_xml.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../profile_helper' 2 | 3 | xml = read_big_xml 4 | 5 | profile_memory('xml/lexer/big_xml') do 6 | Oga::XML::Lexer.new(xml).advance { } 7 | end 8 | -------------------------------------------------------------------------------- /profile/xml/lexer/big_xml_io.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../profile_helper' 2 | 3 | profile_memory('xml/lexer/big_xml') do 4 | Oga::XML::Lexer.new(big_xml_file).advance { } 5 | end 6 | -------------------------------------------------------------------------------- /profile/xml/parser/big_xml.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../profile_helper' 2 | 3 | xml = read_big_xml 4 | 5 | profile_memory('xml/parser/big_xml') do 6 | Oga::XML::Parser.new(xml).parse 7 | end 8 | -------------------------------------------------------------------------------- /profile/xml/pull_parser/big_xml.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../profile_helper' 2 | 3 | xml = read_big_xml 4 | 5 | profile_memory('xml/pull_parser/big_xml') do 6 | Oga::XML::PullParser.new(xml).parse { } 7 | end 8 | 9 | -------------------------------------------------------------------------------- /spec/oga/blacklist_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::Blacklist do 4 | describe '#each' do 5 | it 'yields each value in the list' do 6 | list = described_class.new(%w{foo bar}) 7 | 8 | expect { |block| list.each(&block) } 9 | .to yield_successive_args('foo', 'bar', 'FOO', 'BAR') 10 | end 11 | end 12 | 13 | describe '#allow?' do 14 | it 'returns true for a name not in the list' do 15 | list = described_class.new(%w{foo}) 16 | 17 | expect(list.allow?('bar')).to eq(true) 18 | expect(list.allow?('BAR')).to eq(true) 19 | end 20 | 21 | it 'returns false for a name in the list' do 22 | list = described_class.new(%w{foo}) 23 | 24 | expect(list.allow?('foo')).to eq(false) 25 | expect(list.allow?('FOO')).to eq(false) 26 | end 27 | end 28 | 29 | describe '#+' do 30 | it 'returns a new Blacklist' do 31 | list1 = described_class.new(%w{foo}) 32 | list2 = described_class.new(%w{bar}) 33 | list3 = list1 + list2 34 | 35 | expect(list3).to be_an_instance_of(described_class) 36 | expect(list3.names.to_a).to eq(%w{foo FOO bar BAR}) 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /spec/oga/css/compiler/classes_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'CSS selector evaluation' do 4 | describe 'classes' do 5 | it 'returns a node set containing a node with a single class' do 6 | document = parse('') 7 | 8 | expect(evaluate_css(document, '.foo')).to eq(document.children) 9 | end 10 | 11 | it 'returns a node set containing a node having one of two classes' do 12 | document = parse('') 13 | 14 | expect(evaluate_css(document, '.foo')).to eq(document.children) 15 | end 16 | 17 | it 'returns a node set containing a node having both classes' do 18 | document = parse('') 19 | 20 | expect(evaluate_css(document, '.foo.bar')).to eq(document.children) 21 | end 22 | 23 | it 'returns an empty node set for non matching classes' do 24 | document = parse('') 25 | 26 | expect(evaluate_css(document, '.foo')).to eq(node_set) 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /spec/oga/css/compiler/ids_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'CSS selector evaluation' do 4 | describe 'IDs' do 5 | before do 6 | @document = parse('') 7 | end 8 | 9 | it 'returns a node set containing a node with a single ID' do 10 | expect(evaluate_css(@document, '#foo')).to eq(@document.children) 11 | end 12 | 13 | it 'returns an empty node set for non matching IDs' do 14 | expect(evaluate_css(@document, '#bar')).to eq(node_set) 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /spec/oga/css/compiler/paths_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'CSS selector evaluation' do 4 | describe 'paths' do 5 | before do 6 | @document = parse('') 7 | 8 | @a1 = @document.children[0] 9 | @b1 = @a1.children[0] 10 | @b2 = @a1.children[1] 11 | @c1 = @a1.children[2] 12 | end 13 | 14 | it 'returns a node set containing the root node' do 15 | expect(evaluate_css(@document, 'a')).to eq(node_set(@a1)) 16 | end 17 | 18 | it 'returns a node set containing nested nodes' do 19 | expect(evaluate_css(@document, 'a b')).to eq(node_set(@b1, @b2)) 20 | end 21 | 22 | it 'returns a node set containing the union of multiple paths' do 23 | expect(evaluate_css(@document, 'b, ns1|c')).to eq(node_set(@b1, @b2, @c1)) 24 | end 25 | 26 | it 'returns a node set containing namespaced nodes' do 27 | expect(evaluate_css(@document, 'a ns1|c')).to eq(node_set(@c1)) 28 | end 29 | 30 | it 'returns a node set containing wildcard nodes' do 31 | expect(evaluate_css(@document, 'a *')).to eq(node_set(@b1, @b2, @c1)) 32 | end 33 | 34 | it 'returns a node set containing nodes with namespace wildcards' do 35 | evaluate_css(@document, 'a *|c') 36 | end 37 | 38 | it 'returns a node set containing nodes with a namespace name and name wildcard' do 39 | expect(evaluate_css(@document, 'a ns1|*')).to eq(node_set(@c1)) 40 | end 41 | 42 | it 'returns a node set containing nodes using full wildcards' do 43 | expect(evaluate_css(@document, 'a *|*')).to eq(node_set(@b1, @b2, @c1)) 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /spec/oga/css/compiler/predicates_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'CSS selector evaluation' do 4 | describe 'predicates' do 5 | before do 6 | @document = parse('') 7 | 8 | @a1 = @document.children[0].children[0] 9 | end 10 | 11 | it 'returns a node set containing nodes with an attribute' do 12 | expect(evaluate_css(@document, 'root a[class]')).to eq(node_set(@a1)) 13 | end 14 | 15 | it 'returns a node set containing nodes with a matching attribute value' do 16 | expect(evaluate_css(@document, 'root a[class="foo"]')).to eq(node_set(@a1)) 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /spec/oga/css/compiler/pseudo_classes/empty_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'CSS selector evaluation' do 4 | describe ':empty pseudo class' do 5 | before do 6 | @document = parse('foo') 7 | 8 | @a1 = @document.children[0].children[0] 9 | @b1 = @document.children[0].children[1] 10 | end 11 | 12 | it 'returns a node set containing empty nodes' do 13 | expect(evaluate_css(@document, 'root :empty')).to eq(node_set(@a1)) 14 | end 15 | 16 | it 'returns a node set containing empty nodes with a node test' do 17 | expect(evaluate_css(@document, 'root a:empty')).to eq(node_set(@a1)) 18 | end 19 | 20 | it 'returns an empty node set containing non empty nodes' do 21 | expect(evaluate_css(@document, 'root b:empty')).to eq(node_set) 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /spec/oga/css/compiler/pseudo_classes/first_child_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'CSS selector evaluation' do 4 | describe ':first-child pseudo class' do 5 | before do 6 | @document = parse('') 7 | 8 | @a1 = @document.children[0].children[0] 9 | @b1 = @document.children[0].children[1] 10 | end 11 | 12 | it 'returns a node set containing the first child node' do 13 | expect(evaluate_css(@document, 'root :first-child')).to eq(node_set(@a1)) 14 | end 15 | 16 | it 'returns a node set containing the first child node with a node test' do 17 | expect(evaluate_css(@document, 'root a:first-child')).to eq(node_set(@a1)) 18 | end 19 | 20 | it 'returns an empty node set for non first-child nodes' do 21 | expect(evaluate_css(@document, 'root b:first-child')).to eq(node_set) 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /spec/oga/css/compiler/pseudo_classes/first_of_type_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'CSS selector evaluation' do 4 | describe ':first-of-type pseudo class' do 5 | before do 6 | @document = parse(<<-EOF) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | EOF 15 | 16 | @a1 = @document.at_xpath('root/a[1]') 17 | @a3 = @document.at_xpath('root/a[2]/a[1]') 18 | end 19 | 20 | it 'returns a node set containing all first nodes' do 21 | expect(evaluate_css(@document, 'root a:first-of-type')) 22 | .to eq(node_set(@a1, @a3)) 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /spec/oga/css/compiler/pseudo_classes/last_child_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'CSS selector evaluation' do 4 | describe ':last-child pseudo class' do 5 | before do 6 | @document = parse('') 7 | 8 | @a1 = @document.children[0].children[0] 9 | @b1 = @document.children[0].children[1] 10 | end 11 | 12 | it 'returns a node set containing the last child node' do 13 | expect(evaluate_css(@document, 'root :last-child')).to eq(node_set(@b1)) 14 | end 15 | 16 | it 'returns a node set containing the last child node with a node test' do 17 | expect(evaluate_css(@document, 'root b:last-child')).to eq(node_set(@b1)) 18 | end 19 | 20 | it 'returns an empty node set for non last-child nodes' do 21 | expect(evaluate_css(@document, 'root a:last-child')).to eq(node_set) 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /spec/oga/css/compiler/pseudo_classes/last_of_type_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'CSS selector evaluation' do 4 | describe ':last-of-type pseudo class' do 5 | before do 6 | @document = parse(<<-EOF) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | EOF 15 | 16 | @a2 = @document.at_xpath('root/a[2]') 17 | @a4 = @document.at_xpath('root/a[2]/a[2]') 18 | end 19 | 20 | it 'returns a node set containing all last nodes' do 21 | expect(evaluate_css(@document, 'root a:last-of-type')) 22 | .to eq(node_set(@a2, @a4)) 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /spec/oga/css/compiler/pseudo_classes/nth_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'CSS selector evaluation' do 4 | describe ':nth pseudo class' do 5 | before do 6 | @document = parse('') 7 | 8 | @root = @document.children[0] 9 | @a1 = @root.children[0] 10 | @a2 = @root.children[1] 11 | end 12 | 13 | it 'returns a node set containing the first node' do 14 | expect(evaluate_css(@document, 'root a:nth(1)')).to eq(node_set(@a1)) 15 | end 16 | 17 | it 'returns a node set containing the second node' do 18 | expect(evaluate_css(@document, 'root a:nth(2)')).to eq(node_set(@a2)) 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/oga/css/compiler/pseudo_classes/only_child_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'CSS selector evaluation' do 4 | describe ':only-child pseudo class' do 5 | before do 6 | @document = parse('') 7 | 8 | @root = @document.children[0] 9 | @c1 = @root.children[0].children[0] 10 | @c2 = @root.children[1].children[0] 11 | end 12 | 13 | it 'returns a node set containing nodes' do 14 | expect(evaluate_css(@document, 'root :only-child')).to eq(node_set(@c1, @c2)) 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /spec/oga/css/compiler/pseudo_classes/only_of_type_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'CSS selector evaluation' do 4 | describe ':only-of-type pseudo class' do 5 | before do 6 | @document = parse('') 7 | 8 | @root = @document.children[0] 9 | @c1 = @root.children[0].children[0] 10 | @c2 = @root.children[1].children[0] 11 | end 12 | 13 | it 'returns a node set containing nodes' do 14 | expect(evaluate_css(@document, 'root a :only-of-type')).to eq(node_set(@c1)) 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /spec/oga/css/compiler/pseudo_classes/root_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'CSS selector evaluation' do 4 | describe ':root pseudo class' do 5 | before do 6 | @document = parse('') 7 | end 8 | 9 | it 'returns a node set containing the root node' do 10 | expect(evaluate_css(@document, ':root')).to eq(@document.children) 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /spec/oga/css/lexer/namespaces_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::CSS::Lexer do 4 | describe 'namespaces' do 5 | it 'lexes a path containing a namespace name' do 6 | expect(lex_css('foo|bar')).to eq([ 7 | [:T_IDENT, 'foo'], 8 | [:T_PIPE, nil], 9 | [:T_IDENT, 'bar'] 10 | ]) 11 | end 12 | 13 | it 'lexes a path containing a namespace wildcard' do 14 | expect(lex_css('*|foo')).to eq([ 15 | [:T_IDENT, '*'], 16 | [:T_PIPE, nil], 17 | [:T_IDENT, 'foo'] 18 | ]) 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/oga/css/lexer/predicates_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::CSS::Lexer do 4 | describe 'predicates' do 5 | it 'lexes a path containing a simple predicate' do 6 | expect(lex_css('foo[bar]')).to eq([ 7 | [:T_IDENT, 'foo'], 8 | [:T_LBRACK, nil], 9 | [:T_IDENT, 'bar'], 10 | [:T_RBRACK, nil] 11 | ]) 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /spec/oga/css/lexer/strings_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::CSS::Lexer do 4 | describe 'strings' do 5 | it 'lexes a single quoted string' do 6 | expect(lex_css("['foo']")).to eq([ 7 | [:T_LBRACK, nil], 8 | [:T_STRING, 'foo'], 9 | [:T_RBRACK, nil] 10 | ]) 11 | end 12 | 13 | it 'lexes a double quoted string' do 14 | expect(lex_css('["foo"]')).to eq([ 15 | [:T_LBRACK, nil], 16 | [:T_STRING, 'foo'], 17 | [:T_RBRACK, nil] 18 | ]) 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/oga/css/lexer_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::CSS::Lexer do 4 | it 'ignores leading and trailing whitespace' do 5 | expect(lex_css(' foo ')).to eq([[:T_IDENT, 'foo']]) 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/oga/css/parser/cache_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::CSS::Parser do 4 | describe 'parse_with_cache' do 5 | after do 6 | described_class::CACHE.clear 7 | end 8 | 9 | it 'parses an expression' do 10 | expect(described_class.parse_with_cache('foo')) 11 | .to eq(s(:axis, 'descendant', s(:test, nil, 'foo'))) 12 | end 13 | 14 | it 'caches an expression after parsing it' do 15 | expect_any_instance_of(described_class) 16 | .to receive(:parse) 17 | .once 18 | .and_call_original 19 | 20 | expect(described_class.parse_with_cache('foo')) 21 | .to eq(s(:axis, 'descendant', s(:test, nil, 'foo'))) 22 | 23 | expect(described_class.parse_with_cache('foo')) 24 | .to eq(s(:axis, 'descendant', s(:test, nil, 'foo'))) 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /spec/oga/css/parser/classes_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::CSS::Parser do 4 | describe 'classes' do 5 | it 'parses a class selector' do 6 | expect(parse_css('.foo')).to eq(parse_xpath( 7 | 'descendant::*[contains(concat(" ", @class, " "), " foo ")]' 8 | )) 9 | end 10 | 11 | it 'parses a selector for an element with a class' do 12 | expect(parse_css('foo.bar')).to eq(parse_xpath( 13 | 'descendant::foo[contains(concat(" ", @class, " "), " bar ")]' 14 | )) 15 | end 16 | 17 | it 'parses a selector using multiple classes' do 18 | expect(parse_css('.foo.bar')).to eq(parse_xpath( 19 | 'descendant::*[contains(concat(" ", @class, " "), " foo ") ' \ 20 | 'and contains(concat(" ", @class, " "), " bar ")]' 21 | )) 22 | end 23 | 24 | it 'parses a selector using a class and an ID' do 25 | expect(parse_css('#foo.bar')).to eq(parse_xpath( 26 | 'descendant::*[@id="foo" and ' \ 27 | 'contains(concat(" ", @class, " "), " bar ")]' 28 | )) 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /spec/oga/css/parser/ids_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::CSS::Parser do 4 | describe 'IDs' do 5 | it 'parses an ID selector' do 6 | expect(parse_css('#foo')).to eq(parse_xpath('descendant::*[@id="foo"]')) 7 | end 8 | 9 | it 'parses a selector for an element with an ID' do 10 | expect(parse_css('foo#bar')).to eq(parse_xpath('descendant::foo[@id="bar"]')) 11 | end 12 | 13 | it 'parses a selector using multiple IDs' do 14 | expect(parse_css('#foo#bar')).to eq(parse_xpath( 15 | 'descendant::*[@id="foo" and @id="bar"]' 16 | )) 17 | end 18 | 19 | it 'parses a selector using an ID and a class' do 20 | expect(parse_css('.foo#bar')).to eq(parse_xpath( 21 | 'descendant::*[contains(concat(" ", @class, " "), " foo ") ' \ 22 | 'and @id="bar"]' 23 | )) 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /spec/oga/css/parser/operators_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::CSS::Parser do 4 | describe 'operators' do 5 | it 'parses the = operator' do 6 | expect(parse_css('x[a="b"]')).to eq(parse_xpath('descendant::x[@a="b"]')) 7 | end 8 | 9 | it 'parses the ~= operator' do 10 | expect(parse_css('x[a~="b"]')).to eq(parse_xpath( 11 | 'descendant::x[contains(concat(" ", @a, " "), ' \ 12 | 'concat(" ", "b", " "))]' 13 | )) 14 | end 15 | 16 | it 'parses the ^= operator' do 17 | expect(parse_css('x[a^="b"]')).to eq(parse_xpath( 18 | 'descendant::x[starts-with(@a, "b")]' 19 | )) 20 | end 21 | 22 | it 'parses the $= operator' do 23 | expect(parse_css('x[a$="b"]')).to eq(parse_xpath( 24 | 'descendant::x[substring(@a, string-length(@a) - ' \ 25 | 'string-length("b") + 1, string-length("b")) = "b"]' 26 | )) 27 | end 28 | 29 | it 'parses the *= operator' do 30 | expect(parse_css('x[a*="b"]')).to eq(parse_xpath( 31 | 'descendant::x[contains(@a, "b")]' 32 | )) 33 | end 34 | 35 | it 'parses the |= operator' do 36 | expect(parse_css('x[a|="b"]')).to eq(parse_xpath( 37 | 'descendant::x[@a = "b" or starts-with(@a, concat("b", "-"))]' 38 | )) 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /spec/oga/css/parser/paths_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::CSS::Parser do 4 | describe 'paths' do 5 | it 'parses a single path' do 6 | expect(parse_css('foo')).to eq(parse_xpath('descendant::foo')) 7 | end 8 | 9 | it 'parses a path using a namespace' do 10 | expect(parse_css('ns|foo')).to eq(parse_xpath('descendant::ns:foo')) 11 | end 12 | 13 | it 'parses a path using two selectors' do 14 | expect(parse_css('foo bar')).to eq( 15 | parse_xpath('descendant::foo/descendant::bar') 16 | ) 17 | end 18 | 19 | it 'parses two paths separated by a comma' do 20 | expect(parse_css('foo, bar')).to eq( 21 | parse_xpath('descendant::foo | descendant::bar') 22 | ) 23 | end 24 | 25 | it 'parses three paths separated by a comma' do 26 | expect(parse_css('foo, bar, baz')).to eq( 27 | parse_xpath('descendant::foo | descendant::bar | descendant::baz') 28 | ) 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /spec/oga/css/parser/predicates_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::CSS::Parser do 4 | describe 'predicates' do 5 | it 'parses a predicate' do 6 | expect(parse_css('foo[bar]')).to eq(parse_xpath('descendant::foo[@bar]')) 7 | end 8 | 9 | it 'parses a node test followed by a node test with a predicate' do 10 | expect(parse_css('foo bar[baz]')).to eq(parse_xpath( 11 | 'descendant::foo/descendant::bar[@baz]' 12 | )) 13 | end 14 | 15 | it 'parses a predicate testing an attribute value' do 16 | expect(parse_css('foo[bar="baz"]')).to eq(parse_xpath( 17 | 'descendant::foo[@bar="baz"]' 18 | )) 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/oga/css/parser/pseudo_classes/empty_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::CSS::Parser do 4 | describe ':empty pseudo class' do 5 | it 'parses the :empty pseudo class' do 6 | expect(parse_css(':empty')).to eq(parse_xpath('descendant::*[not(node())]')) 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/oga/css/parser/pseudo_classes/first_child_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::CSS::Parser do 4 | describe ':first-child pseudo class' do 5 | it 'parses the :first-child pseudo class' do 6 | expect(parse_css(':first-child')).to eq(parse_xpath( 7 | 'descendant::*[count(preceding-sibling::*) = 0]' 8 | )) 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /spec/oga/css/parser/pseudo_classes/first_of_type_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::CSS::Parser do 4 | describe ':first-of-type pseudo class' do 5 | it 'parses the :first-of-type pseudo class' do 6 | expect(parse_css(':first-of-type')).to eq(parse_xpath( 7 | 'descendant::*[count(preceding-sibling::*) = 0]' 8 | )) 9 | end 10 | 11 | it 'parses the a:first-of-type pseudo class' do 12 | expect(parse_css('a:first-of-type')).to eq(parse_xpath( 13 | 'descendant::a[count(preceding-sibling::a) = 0]' 14 | )) 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /spec/oga/css/parser/pseudo_classes/last_child_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::CSS::Parser do 4 | describe ':last-child pseudo class' do 5 | it 'parses the :last-child pseudo class' do 6 | expect(parse_css(':last-child')).to eq(parse_xpath( 7 | 'descendant::*[count(following-sibling::*) = 0]' 8 | )) 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /spec/oga/css/parser/pseudo_classes/last_of_type_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::CSS::Parser do 4 | describe ':last-of-type pseudo class' do 5 | it 'parses the :last-of-type pseudo class' do 6 | expect(parse_css(':last-of-type')).to eq(parse_xpath( 7 | 'descendant::*[count(following-sibling::*) = 0]' 8 | )) 9 | end 10 | 11 | it 'parses the a:last-of-type pseudo class' do 12 | expect(parse_css('a:last-of-type')).to eq(parse_xpath( 13 | 'descendant::a[count(following-sibling::a) = 0]' 14 | )) 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /spec/oga/css/parser/pseudo_classes/not_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::CSS::Parser do 4 | describe ':not pseudo class' do 5 | it 'parses the :not(x) pseudo class' do 6 | expect(parse_css(':not(x)')).to eq(parse_xpath('descendant::*[not(self::x)]')) 7 | end 8 | 9 | it 'parses the x:not(y) pseudo class' do 10 | expect(parse_css('x:not(y)')).to eq(parse_xpath('descendant::x[not(self::y)]')) 11 | end 12 | 13 | it 'parses the x:not(#foo) pseudo class' do 14 | expect(parse_css('x:not(#foo)')).to eq( 15 | parse_xpath('descendant::x[not(@id="foo")]') 16 | ) 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /spec/oga/css/parser/pseudo_classes/nth_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::CSS::Parser do 4 | describe ':nth pseudo class' do 5 | it 'parses the :nth(1) pseudo class' do 6 | expect(parse_css(':nth(1)')) 7 | .to eq(parse_xpath('descendant::*[position() = 1]')) 8 | end 9 | 10 | it 'parses the :nth(2) pseudo class' do 11 | expect(parse_css(':nth(2)')) 12 | .to eq(parse_xpath('descendant::*[position() = 2]')) 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /spec/oga/css/parser/pseudo_classes/only_child_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::CSS::Parser do 4 | describe ':only-child pseudo class' do 5 | it 'parses the :only-child pseudo class' do 6 | expect(parse_css(':only-child')).to eq(parse_xpath( 7 | 'descendant::*[count(preceding-sibling::*) = 0 ' \ 8 | 'and count(following-sibling::*) = 0]' 9 | )) 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /spec/oga/css/parser/pseudo_classes/only_of_type_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::CSS::Parser do 4 | describe ':only-of-type pseudo class' do 5 | it 'parses the :only-of-type pseudo class' do 6 | expect(parse_css(':only-of-type')).to eq(parse_xpath( 7 | 'descendant::*[count(preceding-sibling::*) = 0 and ' \ 8 | 'count(following-sibling::*) = 0]' 9 | )) 10 | end 11 | 12 | it 'parses the a:only-of-type pseudo class' do 13 | expect(parse_css('a:only-of-type')).to eq(parse_xpath( 14 | 'descendant::a[count(preceding-sibling::a) = 0 and ' \ 15 | 'count(following-sibling::a) = 0]' 16 | )) 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /spec/oga/css/parser/pseudo_classes/root_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::CSS::Parser do 4 | describe ':root pseudo class' do 5 | it 'parses the x:root pseudo class' do 6 | expect(parse_css('x:root')).to eq(parse_xpath('descendant::x[not(parent::*)]')) 7 | end 8 | 9 | it 'parses the :root pseudo class' do 10 | expect(parse_css(':root')).to eq(parse_xpath('descendant::*[not(parent::*)]')) 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /spec/oga/css/parser/wildcards_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::CSS::Parser do 4 | describe 'wildcards' do 5 | it 'parses a wildcard name test' do 6 | expect(parse_css('*')).to eq(parse_xpath('descendant::*')) 7 | end 8 | 9 | it 'parses a wildcard namespace test' do 10 | expect(parse_css('*|foo')).to eq(parse_xpath('descendant::*:foo')) 11 | end 12 | 13 | it 'parses a wildcard namespace and name test' do 14 | expect(parse_css('*|*')).to eq(parse_xpath('descendant::*:*')) 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /spec/oga/entity_decoder_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::EntityDecoder do 4 | describe 'try_decode' do 5 | it 'returns nil if the input is also nil' do 6 | expect(described_class.try_decode(nil)).to be_nil 7 | end 8 | 9 | it 'decodes XML entities' do 10 | expect(described_class.try_decode('<')) 11 | .to eq(Oga::XML::Entities::DECODE_MAPPING['<']) 12 | end 13 | 14 | it 'decodes HTML entities' do 15 | expect(described_class.try_decode('©', true)) 16 | .to eq(Oga::HTML::Entities::DECODE_MAPPING['©']) 17 | end 18 | end 19 | 20 | describe 'decode' do 21 | it 'decodes XML entities' do 22 | expect(described_class.decode('<')) 23 | .to eq(Oga::XML::Entities::DECODE_MAPPING['<']) 24 | end 25 | 26 | it 'decodes HTML entities' do 27 | expect(described_class.decode('©', true)) 28 | .to eq(Oga::HTML::Entities::DECODE_MAPPING['©']) 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /spec/oga/html/entities_spec.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'spec_helper' 4 | 5 | describe Oga::HTML::Entities do 6 | describe 'decode' do 7 | it 'decodes & into &' do 8 | expect(described_class.decode('&')).to eq('&') 9 | end 10 | 11 | it 'decodes λ into λ' do 12 | expect(described_class.decode('λ')).to eq('λ') 13 | end 14 | 15 | it 'decodes ½ into ½' do 16 | expect(described_class.decode('½')).to eq('½') 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /spec/oga/html/lexer/closing_mismatch_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::XML::Lexer do 4 | describe 'closing HTML elements with mismatched closing tags' do 5 | it 'lexes a

element closed using a element' do 6 | expect(lex_html('

foo')).to eq([ 7 | [:T_ELEM_NAME, 'p', 1], 8 | [:T_TEXT, 'foo', 1], 9 | [:T_ELEM_END, nil, 1] 10 | ]) 11 | end 12 | 13 | it 'lexes a element' do 14 | expect(lex_html('')).to eq([ 15 | [:T_ELEM_NAME, 'object', 1], 16 | [:T_ELEM_NAME, 'param', 1], 17 | [:T_ELEM_END, nil, 1], 18 | [:T_ELEM_NAME, 'param', 1], 19 | [:T_ELEM_END, nil, 1], 20 | [:T_ELEM_END, nil, 1] 21 | ]) 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /spec/oga/html/lexer/closing_rules/body_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::XML::Lexer do 4 | describe 'using HTML elements' do 5 | it 'lexes an unclosed followed by a as separate elements' do 6 | expect(lex_html('foobar')).to eq([ 7 | [:T_ELEM_NAME, 'body', 1], 8 | [:T_TEXT, 'foo', 1], 9 | [:T_ELEM_END, nil, 1], 10 | [:T_ELEM_NAME, 'head', 1], 11 | [:T_TEXT, 'bar', 1], 12 | [:T_ELEM_END, nil, 1] 13 | ]) 14 | end 15 | 16 | it 'lexes an unclosed followed by a as separate elements' do 17 | expect(lex_html('foobar')).to eq([ 18 | [:T_ELEM_NAME, 'body', 1], 19 | [:T_TEXT, 'foo', 1], 20 | [:T_ELEM_END, nil, 1], 21 | [:T_ELEM_NAME, 'body', 1], 22 | [:T_TEXT, 'bar', 1], 23 | [:T_ELEM_END, nil, 1] 24 | ]) 25 | end 26 | 27 | it 'lexes a

following an unclosed as a child element' do 28 | expect(lex_html('

foo')).to eq([ 29 | [:T_ELEM_NAME, 'body', 1], 30 | [:T_ELEM_NAME, 'p', 1], 31 | [:T_TEXT, 'foo', 1], 32 | [:T_ELEM_END, nil, 1], 33 | [:T_ELEM_END, nil, 1] 34 | ]) 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /spec/oga/html/lexer/closing_rules/colgroup_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Oga::XML::Lexer do 4 | describe 'using HTML elements' do 5 | it 'lexes two unclosed elements as separate elements' do 6 | expect(lex_html('foobar')).to eq([ 7 | [:T_ELEM_NAME, 'colgroup', 1], 8 | [:T_TEXT, 'foo', 1], 9 | [:T_ELEM_END, nil, 1], 10 | [:T_ELEM_NAME, 'colgroup', 1], 11 | [:T_TEXT, 'bar', 1], 12 | [:T_ELEM_END, nil, 1] 13 | ]) 14 | end 15 | 16 | it 'lexes a element following a as a child element' do 17 | expect(lex_html('')).to eq([ 18 | [:T_ELEM_NAME, 'colgroup', 1], 19 | [:T_ELEM_NAME, 'col', 1], 20 | [:T_ELEM_END, nil, 1], 21 | [:T_ELEM_END, nil, 1] 22 | ]) 23 | end 24 | 25 | it 'lexes a