{"id":13463262,"url":"https://github.com/opal/opal","last_synced_at":"2025-05-13T17:04:10.850Z","repository":{"id":553846,"uuid":"184366","full_name":"opal/opal","owner":"opal","description":"Ruby ♥︎ JavaScript","archived":false,"fork":false,"pushed_at":"2025-04-04T07:57:43.000Z","size":21076,"stargazers_count":4860,"open_issues_count":148,"forks_count":330,"subscribers_count":95,"default_branch":"master","last_synced_at":"2025-05-06T16:12:57.336Z","etag":null,"topics":["browser","compiler","javascript","js","nodejs","opal","ruby"],"latest_commit_sha":null,"homepage":"https://opalrb.com","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/opal.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"open_collective":"opal"}},"created_at":"2009-04-24T08:53:34.000Z","updated_at":"2025-04-18T13:45:17.000Z","dependencies_parsed_at":"2024-01-07T12:14:27.742Z","dependency_job_id":"50f76afb-4464-459b-902c-b4ac6ae01aec","html_url":"https://github.com/opal/opal","commit_stats":{"total_commits":7495,"total_committers":144,"mean_commits":"52.048611111111114","dds":0.724216144096064,"last_synced_commit":"c4a06f55d5fcacbe77161168282bdf8a8933dde7"},"previous_names":[],"tags_count":156,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opal%2Fopal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opal%2Fopal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opal%2Fopal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opal%2Fopal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/opal","download_url":"https://codeload.github.com/opal/opal/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253518955,"owners_count":21921074,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["browser","compiler","javascript","js","nodejs","opal","ruby"],"created_at":"2024-07-31T13:00:49.234Z","updated_at":"2025-05-13T17:04:10.825Z","avatar_url":"https://github.com/opal.png","language":"Ruby","readme":"\u003ch1 align=\"center\"\u003e\n  \u003cimg src=\"https://secure.gravatar.com/avatar/88298620949a6534d403da2e356c9339?s=420\"\n  align=\"center\" title=\"Opal logo by Elia Schito\" width=\"105\" height=\"105\" /\u003e\n  \u003cbr/\u003e\n  Opal  \u003cbr/\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Opal-Ruby%20💛%20JavaScript-yellow.svg?logo=ruby\u0026style=social\u0026logoColor=777\" alt=\"Opal-Ruby 💛 JavaScript\"/\u003e\n\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cem\u003e\u003cstrong\u003eOpal\u003c/strong\u003e is a Ruby to JavaScript source-to-source compiler.\u003cbr\u003e\n    It also has an implementation of the Ruby \u003ccode\u003ecorelib\u003c/code\u003e and \u003ccode\u003estdlib\u003c/code\u003e.\u003c/em\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eCommunity:\u003c/strong\u003e\u003cbr\u003e\n  \u003ca href=\"https://stackoverflow.com/questions/ask?tags=opalrb\"\u003e\u003cimg src=\"https://img.shields.io/badge/stackoverflow-%23opalrb-orange.svg?style=flat\" alt=\"Stack Overflow\" title=\"\" /\u003e\u003c/a\u003e\n  \u003ca href=\"#backers\"\u003e\u003cimg src=\"https://opencollective.com/opal/backers/badge.svg\" alt=\"Backers on Open Collective\" title=\"\" /\u003e\u003c/a\u003e\n  \u003ca href=\"#sponsors\"\u003e\u003cimg src=\"https://opencollective.com/opal/sponsors/badge.svg\" alt=\"Sponsors on Open Collective\" title=\"\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://slack.opalrb.com/\"\u003e\u003cimg src=\"https://img.shields.io/badge/slack-join%20chat-46BC99?logo=slack\u0026style=flat\" alt=\"Slack\" title=\"Join Chat\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://opalrb.com/docs\"\u003e\u003cimg src=\"https://img.shields.io/badge/docs-updated-blue.svg\" alt=\"Documentation\" title=\"\" /\u003e\u003c/a\u003e\n\n  \u003cbr\u003e\n  \u003cstrong\u003eCode:\u003c/strong\u003e\u003cbr\u003e\n  \u003ca href=\"https://badge.fury.io/rb/opal\"\u003e\u003cimg src=\"https://img.shields.io/gem/v/opal.svg?style=flat\" alt=\"Gem Version\" title=\"\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/opal/opal/actions?query=workflow%3Abuild\"\u003e\u003cimg src=\"https://github.com/opal/opal/workflows/build/badge.svg\" alt=\"Build Status\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://codeclimate.com/github/opal/opal\"\u003e\u003cimg src=\"https://img.shields.io/codeclimate/maintainability-percentage/opal/opal.svg\" alt=\"Code Climate\" title=\"\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://coveralls.io/github/opal/opal?branch=master\"\u003e\u003cimg src=\"https://coveralls.io/repos/opal/opal/badge.svg?branch=master\u0026amp;service=github\" alt=\"Coverage Status\" title=\"\" /\u003e\u003c/a\u003e\n\n  \u003cbr\u003e\n  \u003cstrong\u003eSponsors:\u003c/strong\u003e\n  \u003cbr/\u003e\u003ca href=\"https://nebulab.it?utm_source=github\u0026utm_medium=badge\"\u003e\u003cimg src=\"https://img.shields.io/static/v1?label=Nebulab\u0026message=Open+Source+Fridays\u0026color=%235dbefd\u0026logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMQSURBVHgBrZZNTxNRFIbfczsgIMQiLBCRFDaGhUr9A9iiIa5EEneIwE/AlRsNv8KlIKwFl35RTUBX8rFBdiVKAgqmXSCY0M71nJl+zJTOdKh9k6Yzc8/cZ86555x7CQE0mji5hSyGlQoNaOgIPwrnhtIArWszu4EQFudjdR8rzUV+gw8/ZMZB9IwvIwimJJGafhmjWZwFOJ7QkYzWCwTdj+qUDJGKz8Rou3RAlT4YS+hHWW2u/QdM1MNzrI6+zwyXDrg8FANStIDaSXOIJ5whLgAljOIZiglRK6U4vDfz4S2ElGGJWsEaQkCTUbhtNbV+lb+xgFY2Bs9ET0h/GzBxlfAkqnCUKY5xKfVLbsi1/R126lcF6WgCYp2ES42EBp6tvQFY+alLTUlrUxizJEVNWiVwBkVagGg7oe+CDclLYOfrgMdfTBz8PfWa1lkzbsDEsH/5FyF9YUK0zQ1xwpoZtsm9pwxMRLyA9wyi0A2Jcjl1NNqeeEFEimxYPkmWd014ikIDnDTeBb53DOweaRxnvWGyhnmYfPZWGt487sNi6lsK67/lZ1oZGOtUaD3nhtU7etXXfe0VzrzCBgLKCR68rNDX6oaJlvd0xXnklbSfgSTL/QghXF8EP980cVKyVL/Ys9UDVFJa8Tdt+1lYmcmJM3Vd4UEvWeslRf32h9ubrVRl77gBrCto85OfUU+LXTMGx+JuN2Hoin3/Zkfjj6ObBAknV+KG4jpc9BqXMEpiCMz6Z9ZQ12kvJZxb6co4Zr1W83esY8F2OYsIe+eEyfTiVXczCl7uM2wliHfMEJaRc3Wa++mLUotrF4EW7h6f94Dvh6aVFM60Fy8Xkya+BfBOjh5yUWhqY0vmKi9q1GnVxZ7sHKIWSs7FQ71yUagkRTTCfymnVY1gsgHHC5z8hbUjaz0Fr8ZanXhX0pPOw5SrV8wNGjNscMrTKpXKaj05f9twVYHnMZGPHEuwTwEBNi+3NGiNt6GRcsfEIAfhp2cAV3cQLtXoOz7q8+ZJRLx3kmxn4dy7aas1SrfiBpKraV/9A+PSJLDAXLUvAAAAAElFTkSuQmCC\" alt=\"Nebulab: Open Source Fridays\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n## Usage\n\nSee the website for more detailed instructions and guides for Rails, jQuery, Sinatra, rack, CDN, etc. [https://opalrb.com](https://opalrb.com).\n\n### Compiling Ruby code with the CLI (Command Line Interface)\n\nContents of `app.rb`:\n\n```ruby\nputs 'Hello world!'\n```\n\nThen from the terminal\n\n```bash\n$ opal --compile app.rb \u003e app.js # The Opal runtime is included by default\n                                 # but can be skipped with the --no-opal flag\n```\n\nThe resulting JavaScript file can be used normally from an HTML page:\n\n```html\n\u003cscript src=\"app.js\"\u003e\u003c/script\u003e\n```\n\nBe sure to set the page encoding to `UTF-8` inside your `\u003chead\u003e` tag as follows:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003cmeta charset=\"utf-8\"\u003e\n    \u003cscript src=\"app.js\"\u003e\u003c/script\u003e\n    …\n  \u003c/head\u003e\n  \u003cbody\u003e\n    …\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\nJust open this page in a browser and check the JavaScript console.\n\n\n### Compiling Ruby code from Ruby\n\n`Opal.compile` is a simple interface to just compile a string of Ruby into a\nstring of JavaScript code.\n\n```ruby\nOpal.compile(\"puts 'wow'\")  # =\u003e \"(function() { ... self.$puts(\"wow\"); ... })()\"\n```\n\nRunning this by itself is not enough; you need the opal runtime/corelib.\n\n#### Using Opal::Builder\n\n`Opal::Builder` can be used to build the runtime/corelib into a string.\n\n```ruby\nOpal::Builder.build('opal') #=\u003e \"(function() { ... })()\"\n```\n\nor to build an entire app including dependencies declared with `require`:\n\n```ruby\nbuilder = Opal::Builder.new\nbuilder.build_str('require \"opal\"; puts \"wow\"', '(inline)')\nFile.binwrite 'app.js', builder.to_s # must use binary mode for writing\n```\n\n\n### Compiling Ruby code from HTML (or using it as you would with inline JavaScript)\n\n`opal-parser` allows you to *eval* Ruby code directly from your HTML (and from Opal) files without needing any other building process.\n\nSo you can create a file like the one below, and start writing ruby for\nyour web applications.\n\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003cmeta charset=\"utf-8\"\u003e\n    \u003cscript src=\"https://cdn.opalrb.com/opal/current/opal.js\"\u003e\u003c/script\u003e\n    \u003cscript src=\"https://cdn.opalrb.com/opal/current/opal-parser.js\" onload=\"Opal.load('opal-parser')\"\u003e\u003c/script\u003e\n\n    \u003cscript type=\"text/ruby\"\u003e\n      puts \"hi\"\n    \u003c/script\u003e\n\n  \u003c/head\u003e\n  \u003cbody\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\nJust open this page and check the JavaScript console.\n\n**NOTE**: Although this is possible, this is not really recommended for\nproduction and should only be used as a quick way to get your hands\non opal.\n\n## Running tests\n\nSetup the project:\n\n    $ bin/setup\n\nThe test suite can be run using:\n\n    $ bundle exec rake\n\nThis command will run all RSpec and MSpec examples in sequence.\n\n\n### MSpec\n\n[MSpec][] tests can be run with:\n\n    $ rake mspec\n\nAlternatively, you can just load up a rack instance using `rackup`, and\nvisit `http://localhost:9292/` in any web browser.\n\n\n### RSpec\n\n[RSpec][] tests can be run with:\n\n    $ rake rspec\n\n\n### Automated runs\n\nA `Guardfile` with decent mappings between specs and lib/corelib/stdlib files is in place.\nRun `bundle exec guard -i` to start `guard`.\n\n## Code Overview\n\nWhat code is supposed to run where?\n\n* `lib/` code runs inside your Ruby env. It compiles Ruby to JavaScript.\n* `opal/` is the runtime+corelib for our implementation (runs in browser).\n* `stdlib/` is our implementation of Ruby's stdlib. It is optional (runs in browser).\n\n### lib/\n\nThe `lib` directory holds the **Opal parser/compiler** used to compile Ruby\ninto JavaScript. It is also built ready for the browser into `opal-parser.js`\nto allow compilation in any JavaScript environment.\n\n### opal/\n\nThis directory holds the **Opal runtime and corelib** implemented in Ruby and\nJavaScript.\n\n### stdlib/\n\nHolds the **stdlib currently supported by Opal**. This includes `Observable`,\n`StringScanner`, `Date`, etc.\n\n## Browser support\n\n* Internet Explorer 11\n* Firefox (Current - 1) or Current\n* Chrome (Current - 1) or Current\n* Safari (Current - 1) or Current\n* Opera (Current - 1) or Current\n\nAny problems encountered using the browsers listed above should be reported as bugs.\n\n(Current - 1) or Current denotes that we support the current stable version of\nthe browser and the version that preceded it. For example, if the current\nversion of a browser is 24.x, we support the 24.x and 23.x versions.\n\n12.1x or (Current - 1) or Current denotes that we support Opera 12.1x as well\nas the last 2 versions of Opera. For example, if the current Opera version is 20.x,\nthen we support Opera 12.1x, 19.x and 20.x but not Opera 15.x through 18.x.\n\n## Contributors\n\nThis project exists thanks to all the people who contribute. [![contributors](https://opencollective.com/opal/contributors.svg?width=890\u0026button=false\")](https://github.com/opal/opal/graphs/contributors)\n\n## Versioning\n\nOpal will broadly follow semver as a version policy, trying to bump the major version when introducing breaking changes.\nBeing a language implementation we're also aware that there's a fine line between what can be considered breaking and what is expected to be \"safe\" or just \"additive\". Moving forward we'll attempt to better clarify what interfaces are meant to be public and what should be considered private.\n\n## Backers\n\nThank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/opal#backer)]\n\n\u003ca href=\"https://opencollective.com/opal#backers\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/opal/backers.svg?width=890\" alt=\"Become a Backer Button\" /\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/opal/sponsor/1/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/opal/sponsor/1/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/opal/sponsor/2/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/opal/sponsor/2/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/opal/sponsor/3/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/opal/sponsor/3/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/opal/sponsor/4/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/opal/sponsor/4/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/opal/sponsor/5/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/opal/sponsor/5/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/opal/sponsor/6/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/opal/sponsor/6/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/opal/sponsor/7/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/opal/sponsor/7/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/opal/sponsor/8/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/opal/sponsor/8/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/opal/sponsor/9/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/opal/sponsor/9/avatar.svg\"\u003e\u003c/a\u003e\n\n\n## Sponsors\n\n### Donations\n\nSupport this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/opal#sponsor)]\n\n\u003ca href=\"https://opencollective.com/opal/sponsor/0/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/opal/sponsor/0/avatar.svg\" alt=\"Become a Sponsor Button\"\u003e\u003c/a\u003e\n\n### Sponsored Contributions\n\n\u003ca href=\"https://nebulab.it/?utm_source=github\u0026utm_medium=sponsors\" target=\"_blank\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/solidusio/brand/master/partners/Nebulab/logo-dark-light.svg\" alt=\"Nebulab Logo\"\u003e\u003c/a\u003e\n\n\n## License\n\n(The MIT License)\n\nCopyright (C) 2013-2021 by Adam Beynon and the Opal contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\n[MSpec]: https://github.com/ruby/mspec#readme\n[RSpec]: https://github.com/rspec/rspec#readme\n","funding_links":["https://opencollective.com/opal"],"categories":["JavaScript","Uncategorized","Web 后端","Ruby","Implementations/Compilers"],"sub_categories":["JavaScript Tools","Uncategorized","Inesita"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopal%2Fopal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopal%2Fopal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopal%2Fopal/lists"}