Repository files navigation

This repository constitutes a proof of concept for a Node.js native addon which allows for writing functionality in Swift and exposing it to JavaScript.

To Use

You should be able to run the contents of this repository out of the box, although there are a few small workarounds explained below which you'll have to perform in order to get things working as expected.

# Clone down the repository.
$ git clone https://github.com/codebytere/node-mac-swift-addon
# Change into the addon directory.
$ cd node-mac-swift-addon
# Install dependencies but ignore scripts, because node-gyp runs `node-gyp rebuild` # as a postinstall script and will not invoke my patched version.
$ npm install --ignore-scripts
# Run my patched version of node-gyp, passing the ninja flag.
$ ./node_modules/.bin/node-gyp rebuild --ninja
# This renames the shared library to give it the .node extension# necessary to be able to require and use it in Node.js.
$ npm run move-target
# Run my minimal JavaScript sample.
$ node index.js

Why? How?

This is possible as a result of patches to node-gyp I added in this commit.

node-gyp is a cross-platform command-line tool for compiling native addon modules for Node.js. Out of the gate, it's capable of handling C, C++, and Objective-C++ amongst others, although those three are what you'd typically use to create a native Node.js addon with Nan or node-addon-api.

After Apple announced Big Sur at the 2020 edition of WWDC, I poked around at some of the upcoming APIs that would be made available to developers, and discovered to my chagrin that they would only be made available as Swift APIs, and not have dual Objective-C and Swift support as most Apple APIs for macOS do.

For example, it would be great to be able to access something like WidgetKit in Electron apps via addon, but since it's Swift-only, that's not currently possible.

In order for a native node addon to work properly in Node.js, the compiled addon product must be a shared library. For the last ~year or so Apple has enabled the creation of Mix and Match frameworks with Swift and Objective-C both, and this gave me the idea that I could potentially leverage and mimic this compilation pipeline to generate a shared library file I could then expose into Node.js. After some trial and error I was able to recreate the commands that Xcode runs to generate shared libraries, which culminated in the ability to run the addon contained within this repository.

About

Proof of concept for a Node.js native addon which allows for writing functionality in Swift and exposing it to JavaScript.

Topics

Resources

Stars

59 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

This repository constitutes a proof of concept for a Node.js native addon which allows for writing functionality in Swift and exposing it to JavaScript.

To Use

You should be able to run the contents of this repository out of the box, although there are a few small workarounds explained below which you'll have to perform in order to get things working as expected.

# Clone down the repository.
$ git clone https://github.com/codebytere/node-mac-swift-addon
# Change into the addon directory.
$ cd node-mac-swift-addon
# Install dependencies but ignore scripts, because node-gyp runs `node-gyp rebuild` # as a postinstall script and will not invoke my patched version.
$ npm install --ignore-scripts
# Run my patched version of node-gyp, passing the ninja flag.
$ ./node_modules/.bin/node-gyp rebuild --ninja
# This renames the shared library to give it the .node extension# necessary to be able to require and use it in Node.js.
$ npm run move-target
# Run my minimal JavaScript sample.
$ node index.js

Why? How?

This is possible as a result of patches to node-gyp I added in this commit.

node-gyp is a cross-platform command-line tool for compiling native addon modules for Node.js. Out of the gate, it's capable of handling C, C++, and Objective-C++ amongst others, although those three are what you'd typically use to create a native Node.js addon with Nan or node-addon-api.

After Apple announced Big Sur at the 2020 edition of WWDC, I poked around at some of the upcoming APIs that would be made available to developers, and discovered to my chagrin that they would only be made available as Swift APIs, and not have dual Objective-C and Swift support as most Apple APIs for macOS do.

For example, it would be great to be able to access something like WidgetKit in Electron apps via addon, but since it's Swift-only, that's not currently possible.

In order for a native node addon to work properly in Node.js, the compiled addon product must be a shared library. For the last ~year or so Apple has enabled the creation of Mix and Match frameworks with Swift and Objective-C both, and this gave me the idea that I could potentially leverage and mimic this compilation pipeline to generate a shared library file I could then expose into Node.js. After some trial and error I was able to recreate the commands that Xcode runs to generate shared libraries, which culminated in the ability to run the addon contained within this repository.

About

Proof of concept for a Node.js native addon which allows for writing functionality in Swift and exposing it to JavaScript.

Topics

Resources

Stars

59 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

This repository constitutes a proof of concept for a Node.js native addon which allows for writing functionality in Swift and exposing it to JavaScript.

To Use

You should be able to run the contents of this repository out of the box, although there are a few small workarounds explained below which you'll have to perform in order to get things working as expected.

# Clone down the repository.
$ git clone https://github.com/codebytere/node-mac-swift-addon
# Change into the addon directory.
$ cd node-mac-swift-addon
# Install dependencies but ignore scripts, because node-gyp runs `node-gyp rebuild` # as a postinstall script and will not invoke my patched version.
$ npm install --ignore-scripts
# Run my patched version of node-gyp, passing the ninja flag.
$ ./node_modules/.bin/node-gyp rebuild --ninja
# This renames the shared library to give it the .node extension# necessary to be able to require and use it in Node.js.
$ npm run move-target
# Run my minimal JavaScript sample.
$ node index.js

Why? How?

This is possible as a result of patches to node-gyp I added in this commit.

node-gyp is a cross-platform command-line tool for compiling native addon modules for Node.js. Out of the gate, it's capable of handling C, C++, and Objective-C++ amongst others, although those three are what you'd typically use to create a native Node.js addon with Nan or node-addon-api.

After Apple announced Big Sur at the 2020 edition of WWDC, I poked around at some of the upcoming APIs that would be made available to developers, and discovered to my chagrin that they would only be made available as Swift APIs, and not have dual Objective-C and Swift support as most Apple APIs for macOS do.

For example, it would be great to be able to access something like WidgetKit in Electron apps via addon, but since it's Swift-only, that's not currently possible.

In order for a native node addon to work properly in Node.js, the compiled addon product must be a shared library. For the last ~year or so Apple has enabled the creation of Mix and Match frameworks with Swift and Objective-C both, and this gave me the idea that I could potentially leverage and mimic this compilation pipeline to generate a shared library file I could then expose into Node.js. After some trial and error I was able to recreate the commands that Xcode runs to generate shared libraries, which culminated in the ability to run the addon contained within this repository.

About

Proof of concept for a Node.js native addon which allows for writing functionality in Swift and exposing it to JavaScript.

Topics

Resources

Stars

59 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

This repository constitutes a proof of concept for a Node.js native addon which allows for writing functionality in Swift and exposing it to JavaScript.

To Use

You should be able to run the contents of this repository out of the box, although there are a few small workarounds explained below which you'll have to perform in order to get things working as expected.

# Clone down the repository.
$ git clone https://github.com/codebytere/node-mac-swift-addon
# Change into the addon directory.
$ cd node-mac-swift-addon
# Install dependencies but ignore scripts, because node-gyp runs `node-gyp rebuild` # as a postinstall script and will not invoke my patched version.
$ npm install --ignore-scripts
# Run my patched version of node-gyp, passing the ninja flag.
$ ./node_modules/.bin/node-gyp rebuild --ninja
# This renames the shared library to give it the .node extension# necessary to be able to require and use it in Node.js.
$ npm run move-target
# Run my minimal JavaScript sample.
$ node index.js

Why? How?

This is possible as a result of patches to node-gyp I added in this commit.

node-gyp is a cross-platform command-line tool for compiling native addon modules for Node.js. Out of the gate, it's capable of handling C, C++, and Objective-C++ amongst others, although those three are what you'd typically use to create a native Node.js addon with Nan or node-addon-api.

After Apple announced Big Sur at the 2020 edition of WWDC, I poked around at some of the upcoming APIs that would be made available to developers, and discovered to my chagrin that they would only be made available as Swift APIs, and not have dual Objective-C and Swift support as most Apple APIs for macOS do.

For example, it would be great to be able to access something like WidgetKit in Electron apps via addon, but since it's Swift-only, that's not currently possible.

In order for a native node addon to work properly in Node.js, the compiled addon product must be a shared library. For the last ~year or so Apple has enabled the creation of Mix and Match frameworks with Swift and Objective-C both, and this gave me the idea that I could potentially leverage and mimic this compilation pipeline to generate a shared library file I could then expose into Node.js. After some trial and error I was able to recreate the commands that Xcode runs to generate shared libraries, which culminated in the ability to run the addon contained within this repository.

About

Proof of concept for a Node.js native addon which allows for writing functionality in Swift and exposing it to JavaScript.

Topics

Resources

Stars

59 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

This repository constitutes a proof of concept for a Node.js native addon which allows for writing functionality in Swift and exposing it to JavaScript.

To Use

You should be able to run the contents of this repository out of the box, although there are a few small workarounds explained below which you'll have to perform in order to get things working as expected.

# Clone down the repository.
$ git clone https://github.com/codebytere/node-mac-swift-addon
# Change into the addon directory.
$ cd node-mac-swift-addon
# Install dependencies but ignore scripts, because node-gyp runs `node-gyp rebuild` # as a postinstall script and will not invoke my patched version.
$ npm install --ignore-scripts
# Run my patched version of node-gyp, passing the ninja flag.
$ ./node_modules/.bin/node-gyp rebuild --ninja
# This renames the shared library to give it the .node extension# necessary to be able to require and use it in Node.js.
$ npm run move-target
# Run my minimal JavaScript sample.
$ node index.js

Why? How?

This is possible as a result of patches to node-gyp I added in this commit.

node-gyp is a cross-platform command-line tool for compiling native addon modules for Node.js. Out of the gate, it's capable of handling C, C++, and Objective-C++ amongst others, although those three are what you'd typically use to create a native Node.js addon with Nan or node-addon-api.

After Apple announced Big Sur at the 2020 edition of WWDC, I poked around at some of the upcoming APIs that would be made available to developers, and discovered to my chagrin that they would only be made available as Swift APIs, and not have dual Objective-C and Swift support as most Apple APIs for macOS do.

For example, it would be great to be able to access something like WidgetKit in Electron apps via addon, but since it's Swift-only, that's not currently possible.

In order for a native node addon to work properly in Node.js, the compiled addon product must be a shared library. For the last ~year or so Apple has enabled the creation of Mix and Match frameworks with Swift and Objective-C both, and this gave me the idea that I could potentially leverage and mimic this compilation pipeline to generate a shared library file I could then expose into Node.js. After some trial and error I was able to recreate the commands that Xcode runs to generate shared libraries, which culminated in the ability to run the addon contained within this repository.

About

Proof of concept for a Node.js native addon which allows for writing functionality in Swift and exposing it to JavaScript.

Topics

Resources

Stars

59 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

This repository constitutes a proof of concept for a Node.js native addon which allows for writing functionality in Swift and exposing it to JavaScript.

To Use

You should be able to run the contents of this repository out of the box, although there are a few small workarounds explained below which you'll have to perform in order to get things working as expected.

# Clone down the repository.
$ git clone https://github.com/codebytere/node-mac-swift-addon
# Change into the addon directory.
$ cd node-mac-swift-addon
# Install dependencies but ignore scripts, because node-gyp runs `node-gyp rebuild` # as a postinstall script and will not invoke my patched version.
$ npm install --ignore-scripts
# Run my patched version of node-gyp, passing the ninja flag.
$ ./node_modules/.bin/node-gyp rebuild --ninja
# This renames the shared library to give it the .node extension# necessary to be able to require and use it in Node.js.
$ npm run move-target
# Run my minimal JavaScript sample.
$ node index.js

Why? How?

This is possible as a result of patches to node-gyp I added in this commit.

node-gyp is a cross-platform command-line tool for compiling native addon modules for Node.js. Out of the gate, it's capable of handling C, C++, and Objective-C++ amongst others, although those three are what you'd typically use to create a native Node.js addon with Nan or node-addon-api.

After Apple announced Big Sur at the 2020 edition of WWDC, I poked around at some of the upcoming APIs that would be made available to developers, and discovered to my chagrin that they would only be made available as Swift APIs, and not have dual Objective-C and Swift support as most Apple APIs for macOS do.

For example, it would be great to be able to access something like WidgetKit in Electron apps via addon, but since it's Swift-only, that's not currently possible.

In order for a native node addon to work properly in Node.js, the compiled addon product must be a shared library. For the last ~year or so Apple has enabled the creation of Mix and Match frameworks with Swift and Objective-C both, and this gave me the idea that I could potentially leverage and mimic this compilation pipeline to generate a shared library file I could then expose into Node.js. After some trial and error I was able to recreate the commands that Xcode runs to generate shared libraries, which culminated in the ability to run the addon contained within this repository.

About

Proof of concept for a Node.js native addon which allows for writing functionality in Swift and exposing it to JavaScript.

Topics

Resources

Stars

59 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

This repository constitutes a proof of concept for a Node.js native addon which allows for writing functionality in Swift and exposing it to JavaScript.

To Use

You should be able to run the contents of this repository out of the box, although there are a few small workarounds explained below which you'll have to perform in order to get things working as expected.

# Clone down the repository.
$ git clone https://github.com/codebytere/node-mac-swift-addon
# Change into the addon directory.
$ cd node-mac-swift-addon
# Install dependencies but ignore scripts, because node-gyp runs `node-gyp rebuild` # as a postinstall script and will not invoke my patched version.
$ npm install --ignore-scripts
# Run my patched version of node-gyp, passing the ninja flag.
$ ./node_modules/.bin/node-gyp rebuild --ninja
# This renames the shared library to give it the .node extension# necessary to be able to require and use it in Node.js.
$ npm run move-target
# Run my minimal JavaScript sample.
$ node index.js

Why? How?

This is possible as a result of patches to node-gyp I added in this commit.

node-gyp is a cross-platform command-line tool for compiling native addon modules for Node.js. Out of the gate, it's capable of handling C, C++, and Objective-C++ amongst others, although those three are what you'd typically use to create a native Node.js addon with Nan or node-addon-api.

After Apple announced Big Sur at the 2020 edition of WWDC, I poked around at some of the upcoming APIs that would be made available to developers, and discovered to my chagrin that they would only be made available as Swift APIs, and not have dual Objective-C and Swift support as most Apple APIs for macOS do.

For example, it would be great to be able to access something like WidgetKit in Electron apps via addon, but since it's Swift-only, that's not currently possible.

In order for a native node addon to work properly in Node.js, the compiled addon product must be a shared library. For the last ~year or so Apple has enabled the creation of Mix and Match frameworks with Swift and Objective-C both, and this gave me the idea that I could potentially leverage and mimic this compilation pipeline to generate a shared library file I could then expose into Node.js. After some trial and error I was able to recreate the commands that Xcode runs to generate shared libraries, which culminated in the ability to run the addon contained within this repository.

About

Proof of concept for a Node.js native addon which allows for writing functionality in Swift and exposing it to JavaScript.

Topics

Resources

Stars

59 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

This repository constitutes a proof of concept for a Node.js native addon which allows for writing functionality in Swift and exposing it to JavaScript.

To Use

You should be able to run the contents of this repository out of the box, although there are a few small workarounds explained below which you'll have to perform in order to get things working as expected.

# Clone down the repository.
$ git clone https://github.com/codebytere/node-mac-swift-addon
# Change into the addon directory.
$ cd node-mac-swift-addon
# Install dependencies but ignore scripts, because node-gyp runs `node-gyp rebuild` # as a postinstall script and will not invoke my patched version.
$ npm install --ignore-scripts
# Run my patched version of node-gyp, passing the ninja flag.
$ ./node_modules/.bin/node-gyp rebuild --ninja
# This renames the shared library to give it the .node extension# necessary to be able to require and use it in Node.js.
$ npm run move-target
# Run my minimal JavaScript sample.
$ node index.js

Why? How?

This is possible as a result of patches to node-gyp I added in this commit.

node-gyp is a cross-platform command-line tool for compiling native addon modules for Node.js. Out of the gate, it's capable of handling C, C++, and Objective-C++ amongst others, although those three are what you'd typically use to create a native Node.js addon with Nan or node-addon-api.

After Apple announced Big Sur at the 2020 edition of WWDC, I poked around at some of the upcoming APIs that would be made available to developers, and discovered to my chagrin that they would only be made available as Swift APIs, and not have dual Objective-C and Swift support as most Apple APIs for macOS do.

For example, it would be great to be able to access something like WidgetKit in Electron apps via addon, but since it's Swift-only, that's not currently possible.

In order for a native node addon to work properly in Node.js, the compiled addon product must be a shared library. For the last ~year or so Apple has enabled the creation of Mix and Match frameworks with Swift and Objective-C both, and this gave me the idea that I could potentially leverage and mimic this compilation pipeline to generate a shared library file I could then expose into Node.js. After some trial and error I was able to recreate the commands that Xcode runs to generate shared libraries, which culminated in the ability to run the addon contained within this repository.

About

Proof of concept for a Node.js native addon which allows for writing functionality in Swift and exposing it to JavaScript.

Topics

Resources

Stars

59 stars

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages