') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); GitHub - brynne8/lua2js: Lua to JavaScript Transpiler -- Mirror of https://bitbucket.org/basicer/lua2js · GitHub
Skip to content

Repository files navigation

Lua2JS

A Lua parser and standard library targeting the Mozilla Parser API AST.

Installing

Generated and minified sources are available on NPM

npm install lua2js

Dependencies

  • Development: peg.js
  • Runtime: None =)

Compatibility

Many lua programs run unmodified on lua2js. See the lua-tests folder for some examples.

JavaScript <-> Lua

When the luaCalls option is on, the arguments to javascript functions will be adjusted in the following ways:

  • If the function was being called with : syntax, the variable that would be passed as self is used as this
  • If a LuaTable is passed as an argument if the table only has numeric entries, an array will be passed. If there are no numeric entire, a javascript object will be passed. If both are present, the LuaTable object will be passed.
  • If the last argument is a function that returned multiple values, they will be unpacked as normal.

Lua Syntax Not Supported (Yet)

  • Long form strings and comments will choke on internal ]]'s even when using the [==[ syntax.
  • The goto statement and labels from lua 5.2 are unimplemented.
  • The global environment doesn't exist in _ENV or _G.

Lua Runtime Standard Library

  • pairsipairsnext all work on both lua tables and javascript objects/arrays
  • MetaTable and operator overloading work on LuaTables

Lua Standard Library Holes

  • getmetatable and setmetatable only work on LuaTable's
  • requires and package interface tables are missing.
  • The debug library is missing.
  • The coroutine library is missing (and no runtime support for coroutines exists)`
  • The bit32 library from lua 5.2 is incomplete.
  • string.format is less powerful then the lua version.
  • Pattern matching (string.find, string.match, string.gsub) is unimplemented.
  • Code loading (load, dostring, dofile, etc...) is unimplemented.

Parser Options

Boolean Options

  • decorateLuaObjects: Mark lua functions so __lua.call can call them differently. Also the {} syntax will create a LuaTable object instead of a normal javascript object.
  • encloseWithFunctions: Protect variable scoping by creating functions and calling them.
  • forceVar: Forbid generation of let statements to maintain ES5 compatibility.
  • loose: Try not to throw parse errors, and collect them in ast.errors instead.
  • luaCalls: Rewrite function calls to use __lua.call to fix-up various lua<->javascript calling convention differences.
  • luaOperators: Use functions in the standard library instead of conventional operators to improve Lua compatibility. (e.g. a+b becomes __lua.add(a,b))
  • noSharedObjects: Make sure all AST nodes are unique objects. Can prevent bugs when performing transformations on the returned AST.
  • allowRegularFunctions: Normally all functions are emitted in something = function() { ... } format. Enable this to emit the more normal (but sometimes less compatible) function something() { ... }.

Testing

You can run a suite of tests using the npm test command. The tests require having nodeunit installed globally and a working Lua interpreter on your path. The tests fall into three categories.

  • Simple Tests: These are contained in an array toward the top of test.js and test simple lua programs without the Lua interpreter.
  • ./lua-tests/: A collection of various lua programs from around the internet. These are interpreted in node and their output compared against the systems lua interpreter.
  • ./lua-testmore/: Selected tests from the lua-TestMore project. Similar to the above.

License

Code and documentation copyright 2014 Rob Blanckaert. Code released under the MIT license.

About

Lua to JavaScript Transpiler -- Mirror of https://bitbucket.org/basicer/lua2js

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages