Coder Social home page Coder Social logo

mingyaulee / blazor.browserextension Goto Github PK

View Code? Open in Web Editor NEW
337.0 13.0 35.0 4.1 MB

Build browser extensions easily with Blazor.

Home Page: https://mingyaulee.github.io/Blazor.BrowserExtension/

License: MIT License

C# 10.43% JavaScript 87.11% HTML 1.19% CSS 1.09% PowerShell 0.17%
blazor-webassembly blazor browser-extension chrome-extension firefox-addon firefox-extension msedge-extension edge-extension

blazor.browserextension's Introduction

Blazor.BrowserExtension

Nuget GitHub Workflow Status Sonar Quality Gate

You can now easily build a browser extension with Blazor!

Visit the documentations page to find out more!

blazor.browserextension's People

Contributors

amazingalek avatar dependabot[bot] avatar mingyaulee avatar newbe36524 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

blazor.browserextension's Issues

Ability to change the icon dynamically

Hello,

First, thanks for this wonderful project.

I wonder if it is possible to dynamically change the top right icon based upon states.

For instance, let's say Condition A is met, then I want the icon to be red, if not, then the icon is Yellow.

image

Thanks!

Quick Note on publishing extensions to the Chrome Store - probably should be added to the readme

@mingyaulee

I was able to get my extension added to the Chrome Web Store (in addition to the Edge store).

A couple of things to note about this:

  • Microsoft is far easier to deal with as long as you note somewhere in the testing steps and/or description that the extension uses Blazor. It's slower than Google but it's pretty much a hassle free experience.

  • Google on the other hand will reject your extension at first if you declare any chromium apis in the manifest. Their automated testing doesn't work with Blazor / WASM. Their support has managed to get it straightened out each time, but it's still frustrating.

Needless to say, you may want to note in the read me that developers should expect some difficulty with Google if they wish to publish a Blazor extension to the Chrome store.

The last correspondence I had with Google's support said that they are discussing how to make the submission of WASM extensions easier. So hopefully this isn't a permanent problem.

@page "/contentscript.html" is not working

@page "/contentscript.html"
@inherits BasePage

<h3>ContentScript</h3>

@code {

}
 public partial class ContentScript
    {
    
        [Inject] public IJsRuntimeAdapter JsRuntimeAdapter { get; set; }

        protected override async Task OnInitializedAsync()
        {
            Console.WriteLine("dddd");
            
            await base.OnInitializedAsync();
        }
    }

dddd is not log in console

image

Add support for remote authentication / MSAL.js?

I created an issue in the dotnet/aspnetcore repo bringing up the idea of browser extension support for remote authentication / `Microsoft.Identity.Web. Given this is a separate project not supported by the aspnetcore team, I was a bit skeptical that it wouldn't get closed, but I wanted to hear their feedback first. I linked to a somewhat working implementation on a fork of mine. The official repo makes calls to MSAL.js, and the general gist to add browser extension support is to wrap those calls with chrome.identity.launchWebAuthFlow.

The current fork is a bit buggy still, likely due to my current implementation's dependency on virtual routing. I may be able to iron this out.

I wanted to bring up the discussion of what the best way to incorporate authentication would be from a framework and architecture standpoint.

The Authentication.Msal library ships its own AuthenticationService.ts to use with WebAssembly.Authentication's RemoteAuthenticationService, so it might be possible to produce a library that layers on top of WebAssembly.Authentication like Authentication.Msal does. The advantage of this implementation is interop with existing Msal APIs. I have two Blazor projects, one extension and one hosted SWA, that share a RCL.

If this is possible and desired, the question would be where should the source live? I wouldn't mind spinning up a Blazor.BrowserExtension.Authentication or Blazor.BrowserExtension.Authentication.Msal, but I wouldn't mind working in this repository as well, so I'd like to hear what the direction for this project is, any guidelines, etc.

C# Background Worker?

Hey! So I might have some basic misunderstandings of this framework--but I'm trying to create a Blazor web extension that changes the rendering of a content script based on an option added to the user's right-click context menu. So if the user right clicks a portion of text on a web page and presses the web extension option, they'll receive a read-out from the content script based on the selected text.

I was able to add a right-click option by interfacing with the web extension API in my extension's popup page (Popup.razor)--but that only seems to execute once the popup has been opened. So I tried adding the same code to my content script (ContentScript.razor) to reliably add the right-click option and hook it to the content script--but it appears as though content scripts can't access the full web extension/browser API.

I'm not sure how to accomplish this. Is there a simple way to access the full web extension API using a C# script running reliably in the background? I just want to control menu options/tabs/etc. using a background script in C#, ideally not so different from what's possible in Javascript using BackgroundWorker.js.

Options page not exposed by Firefox

It should be noted that the following is required to appear in the manifest in order for Firefox to expose the options page:

"options_ui": {
"page": "index.html?path=options",
"browser_style": true
},

Menus not work?

 await WebExtensions.Menus.Create(new WebExtensions.Net.Menus.CreateProperties
        {
            Title = "测试",
            Contexts = new List<ContextType> {
                ContextType.Selection
            },
            Onclick =  (data,tab) => {
                 WebExtensions.Tabs.Create(new WebExtensions.Net.Tabs.CreateProperties
                {
                    Url = "https://www.baidu.com/s?ie=utf-8&wd=" + WebUtility.UrlEncode(data.SelectionText)
                }) ;
            }
        }, () => {
            
        });

image

Use of Task.Delay or System.Timers.Timer crashes in content script

Thanks for this awesome project!

Repro steps:

  1. Have await Task.Delay(...) in a content script.

The content script works fine without Task.Delay.

Error:

Uncaught (in promise) TypeError: Cannot read property 'mono_set_timeout_exec' of undefined
    at _mono_set_timeout (dotnet.5.0.5.js:1)
    at mono_wasm_set_timeout (/<anonymous>:wasm-function[6909]:0x1089e2)
    at do_icall (/<anonymous>:wasm-function[10596]:0x194d07)
    at do_icall_wrapper (/<anonymous>:wasm-function[3305]:0x79df9)
    at interp_exec_method (/<anonymous>:wasm-function[2155]:0x44ad3)
    at interp_runtime_invoke (/<anonymous>:wasm-function[7862]:0x12efff)
    at mono_jit_runtime_invoke (/<anonymous>:wasm-function[7347]:0x118e5f)
    at do_runtime_invoke (/<anonymous>:wasm-function[3304]:0x79d42)
    at mono_runtime_try_invoke (/<anonymous>:wasm-function[629]:0x12982)
    at mono_runtime_invoke (/<anonymous>:wasm-function[7118]:0x10ec2b)

This is the code that crashes (in dotnet.5.0.5.js):

function _mono_set_timeout(timeout, id) {
    if (!this.mono_set_timeout_exec)
        this.mono_set_timeout_exec = Module.cwrap("mono_set_timeout_exec", null, ["number"]);
    ...

This issue is that this is undefined. It likely has other consequences as well. Any idea how we can set this to a value for content scripts?

JsBindNet.js get fetchOption fail

image

export async function Fetch(url, init) {
  const response = await fetch(url, init); //should change to 【  init.result 】
  return new FetchResponse(response);
}

image

  var fetchOptions = new Dictionary<string, object>(request.Options)
            {
                ["method"] = request.Method.Method,
// can not set fetchOption headers , so this line  should change to 【request.Content.Headers.ToDictionary(header => header.Key, header => string.Join(',', header.Value)) 】
                ["headers"] = request.Headers.ToDictionary(header => header.Key, header => string.Join(',', header.Value))

            };

Support to load razor class libary

Background

There are some useful razor class libary for developer to build razor application.
We need to support to load them in dev and production.

Proposal

Here is an example of introducing ant-design-blazor

We would normally develop a blazor application using the dev server to help us start a web server during development.
However, the chrome extension is loaded from a folder, so the dev server cannot be used.
This causes us to ignore the static files that are in the razor class libary.
Therefore, we should copy and parse them to the output directory.

After the project is successfully built, we can find the static file configuration xml in the project's obj/Debug/net5.0/staticwebassets, such as the following.

<StaticWebAssets Version="1.0">
  <ContentRoot BasePath="_content/AntDesign" Path="C:\Users\Administrator\.nuget\packages\antdesign\0.8.0\build\..\staticwebassets\" />
  <ContentRoot BasePath="/" Path="C:\Repos\newbe\Newbe.BookmarkManager\src\Newbe.BookmarkManager\bin\Debug\net5.0\wwwroot\" />
  <ContentRoot BasePath="/" Path="C:\Repos\newbe\Newbe.BookmarkManager\src\Newbe.BookmarkManager\obj\Debug\net5.0\scopedcss\bundle\" />
</StaticWebAssets>

The first part of this ``BasePath="_content/AntDesign"` is the location of the static file for a razor class libary.

So, we need to copy these files to the wwwroot/_content/AntDesign folder in the build task.

Tip: _content is not a reserved folder, so you can use this path without renaming it.

Workflows are referencing vulnerable actions

Hello, there!

As part of the university research we are currently doing regarding the security of Github Actions, we noticed that one or many of the workflows that are part of this repository are referencing vulnerable versions of the third-party actions. As part of a disclosure process, we decided to open issues to notify GitHub Community.

Please note that there are could be some false positives in our methodology, thus not all of the open issues could be valid. If that is the case, please let us know, so that we can improve on our approach. You can contact me directly using an email: ikoishy [at] ncsu.edu

Thanks in advance

  1. The workflow Blazor.BrowserExtension-Build.yml is referencing action gittools/actions/gitversion/setup using references v0.9.7. However this reference is missing the commit 90150b4 which may contain fix to the vulnerability.
  2. The workflow Blazor.BrowserExtension-Build.yml is referencing action gittools/actions/gitversion/execute using references v0.9.7. However this reference is missing the commit 90150b4 which may contain fix to the vulnerability.
  3. The workflow Blazor.BrowserExtension-Release.yml is referencing action gittools/actions/gitversion/setup using references v0.9.7. However this reference is missing the commit 90150b4 which may contain fix to the vulnerability.
  4. The workflow Blazor.BrowserExtension-Release.yml is referencing action gittools/actions/gitversion/execute using references v0.9.7. However this reference is missing the commit 90150b4 which may contain fix to the vulnerability.

The vulnerability fix that is missing by actions' versions could be related to:
(1) CVE fix
(2) upgrade of vulnerable dependency
(3) fix to secret leak and others.
Please consider updating the reference to the action.

If you end up updating the reference, please let us know. We need the stats for the paper :-)

Blazor WASM hosted fetch data - Core.js returns 404 ()

How to get blazor wasm comunicate with API? My Program.cs has code:

builder.Services.AddScoped<HttpClient>(sp => new JsHttpClient(sp) { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

My error in the browser:
Failed to load resource: the server responded with a status of 404 ()
Is it possible to get blazor WASM hosted with Blazor.BrowserExtension working on the same IP?
I cannot fetch data from server weather controller.

Exception with latest release

When I referenced the latest release 0.2.0, it seemed it would fail to build, the error is like follows:

image

I had to change the code like below to build the project, wondering if this expected by design?

await WebExtension.Tabs.Create(new WebExtension.Net.Tabs.CreateProperties
{
    Url = extensionUrl
});

Unable to open popup. file not found error

I am trying to create an extension when i create a new project using tempalte and upload to chrome extension after publishing it shows this page
image
i am trying this from tomorrow but unable to make it work.

i am using manifest v3 and dotnet 7 preview version, In dotnet 6 project it's loading assemblies from framework folder but in dotnet 7 it's trying to load from _framework folder.

can you please upload a working example of extension with popup page. Thanks

Question - Extension published featuring Blazor.BrowserExtension - Any specific information you'd like in the listing?

@mingyaulee

I didn't see any other way to contact you with this question, so sorry if this isn't the best way to handle it.

I was able to get approval from Microsoft and they published an extension I made using Blazor.BrowserExtension. It's a simple extension that overrides the Edge new tab page with some additional features / differences.

Right now, I have a note about using Blazor.BrowserExtension on the github site but I forgot to note it on the marketplace listing. Do you want me to add anything about it there? I am not aware of there being any other extensions on the Edge site that make note of using Blazor.

https://microsoftedge.microsoft.com/addons/detail/blazor-edge-new-tab/bfhdepjammnaoddhikhogfbnikmeocfj

How to use HttpClient to access B website from A website across the domain ?

Error message: Access to fetch at 'B' from origin 'A' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

I currently use the 'CORS Unblock' extension to access

Warning in net6 preview

  1. create a project
  2. add Blazor.BrowserExtensions
  3. create mainfest.json
  4. build

There is a warning and I have no idea what it is about.

Blazor.BrowserExtension.Build.targets(145, 5): Unable to find text to replace 'this.mono_wasm_assembly_already_added' in file 'C:\Repos\newbe\Newbe.Demo\src\BlogDemos\Newbe.Blazor\Newbe.Blazor.Template\Newbe.Blazor.Template\bin\Debug\net6.0\wwwroot\framework\dotnet.6.0.0-preview.3.21201.4.js'

And it seem that everything works well event the warning raised

Remove host permission for easier to audit

Background

When trying to upload a extension to the chrome extensions store, it can take longer to review the extension if it requires "host permission".
This is explained in the review prompt page when uploading.
Therefore, we would like to explore a solution to remove the need for "host permission", i.e. remove the need for "*:///*/*" from mainfest.json.

Proposal

It is recommended that developers set all Razor page URLs to end with index.html.

For example.

  • /manager/index.html
  • /popup/index.html
  • /background/index.html

With this setting, users can not only use NavigationManager to jump directly to the page. It is possible to open the interface with a browser, for example /manager/index.html, without getting 404 when refreshing with F5.

To support index.html generation in each path.
You need to automatically create a folder with index.html in the above location and copy index.html to it during building project.

  1. Add a helper class to help developers quickly splice the above special links, for example, to achieve the following effect.
await WebExtension.Tabs.Create(new
{
    url = "/index.html?path=/Manager/index.html"
});

It is possible to use.

await WebExtension.Tabs.Create(new
{
    url = WebExtension.GetPageUrl("/Manager")
});

[BUG] failed to build in net6 preview7

I think the path of StaticWebAssets.xml has been changed in the new SDK version.
Instead of in the obj\Debug\net6.0\staticwebassets folder, it belongs directly obj\Debug\net6.0 now

  Blazor.BrowserExtension.Build.targets(218, 5): [MSB4018] The "BlazorToBrowserExtensionProcessStaticWebAssetsManifest" task failed unexpectedly.
System.IO.FileNotFoundException: Could not find file 'C:\Repos\newbe\Amazing-Favorites\src\Newbe.BookmarkManager\obj\Debug\net6.0\staticwebassets\Newbe.BookmarkManager.StaticWebAssets.xml'.
File name: 'C:\Repos\newbe\Amazing-Favorites\src\Newbe.BookmarkManager\obj\Debug\net6.0\staticwebassets\Newbe.BookmarkManager.StaticWebAssets.xml'
   at Microsoft.Win32.SafeHandles.SafeFileHandle.CreateFile(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options) in System.Private.CoreLib.dll:token 0x6000126+0xbb
   at Microsoft.Win32.SafeHandles.SafeFileHandle.Open(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize) in System.Private.CoreLib.dll:token 0x6000125+0x48
   at System.IO.Strategies.OSFileStreamStrategy..ctor(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize) in System.Private.CoreLib.dll:token 0x600631c+0x78
   at Blazor.BrowserExtension.Build.Tasks.BlazorToBrowserExtensionProcessStaticWebAssetsManifest.Execute() in Blazor.BrowserExtension.Build.dll:token 0x6000029+0x65
   at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute() in Microsoft.Build.dll:token 0x6001602+0x3e
   at Microsoft.Build.BackEnd.TaskBuilder.ExecuteInstantiatedTask(ITaskExecutionHost taskExecutionHost, TaskLoggingContext taskLoggingContext, TaskHost taskHost, ItemBucket bucket, TaskExecutionMode howToExecuteTask) in Microsoft.Build.dll:token 0x6001481+0x804

explorer_EpuMFUDQYN

[BUG] Build error with 0.3.3

github action log:

https://github.com/newbe36524/Amazing-Favorites/pull/38/checks?check_run_id=2774697538

/home/runner/work/Amazing-Favorites/Amazing-Favorites/src/Newbe.BookmarkManager/bin/Release/net6.0/wwwroot/manifest.json(16-16): error : Manifest item 'web_accessible_resources' must specify "framework/*", "BrowserExtensionScripts/*" and "WebExtensionsScripts/*". 

manifest.json

https://github.com/newbe36524/Amazing-Favorites/blob/feature/br/src/Newbe.BookmarkManager/wwwroot/manifest.json

When renaming or moving a project, the wrong file may be copied if the obj folder is not deleted.

  1. create the project tpl1
  2. install the appropriate packages and initialize the project
  3. rename the project folder to tpl2
  4. try to build, it will report an error
  5. delete obj bin
  6. build, success.

Similarly, if the entire project is copied directly, there are problems

  1. create the project tpl1
  2. install the appropriate packages and initialize the project
  3. copy the whole project folder and rename it as tpl2
  4. try to build, no error is reported, but actually the file contents are copied from tpl1
  5. delete obj bin
  6. build, success.

Debugging while running as extension

I know you say there is no way to debug while running as an extension, but is there any way to write to the Chrome dev tools console, or even write alerts? I just want to somehow get some idea of what's happening.

I'm a newbie to Chrome extensions (and Blazor) so apologies if I'm asking a really stupid question!

Manifest including curly braces in property value doesn't build

For some historical reasons we have browser_specific_settings.gecko.id set to a guid with curly braces and build throws an exception The file manifest.json is not well formatted. Each line can only contain one of the characters '{', '}', '[', ']'. Could we somehow ignore the validation if the braces are in a property value?

"browser_specific_settings": {
  "gecko": {
    "id": "{2dac9f13-26f2-401e-af9e-9c5a3ababbb5}"
  }
}

_content renaming missed for RCL

I've noticed that if I pull in a Razor Class Library, the import line in the output "$(ProjectName).styles.css" does not have the "_content" replaced, similar to other files. For now, I created a "PostBuildEvent" with a dependency on "RunBuildBlazorToBrowserExtension" to manually replace that one word, and now the app displays and behaves correctly. I "think" the issue is part of "Blazor.BrowserExtension.Build.Tasks.BlazorToBrowserExtensionProcessStaticWebAssetsManifest" but not 100% sure (didn't evaluate any code). I'm still new to Blazor and the latest AspCore (let alone browser extension), so I could have misunderstood some things, but hopefully, this gets you to the right place.

image

Btw, this is a really awesome project you've got here! It was ridiculously easy to get up and going, even though I'm still fairly new to all three of these technologies (Blazor, AspCore, & browser extensions). The only suggestion I would have is tailoring the samples & templates to be closer to the look and feel of the default Blazor templates, but I was able to get over the hump relatively quickly.

P.S. Looking forward to Chrome getting the WASM issues resolved so that we can use MV3 since MV2 will be dead in the water soon.

Thanks!

blazor.boot.json libraryInitializers incorrect path

This is my first time submitting an issue on a public repository, so forgive my ignorance please 🙂.

Issue:

Uncaught (in promise) TypeError: Failed to fetch dynamically imported module: chrome-extension://[my-chrome-extension-id]/_content/Microsoft.Fast.Components.FluentUI/Microsoft.Fast.Components.FluentUI.lib.module.js
at
content/Blazor.BrowserExtension/Core.js:43 (anonymous function)

I have referenced the above package in my project. In ...\net7.0\browserextension\framework\blazor.boot.json, When I change "_content" to "content" under "libraryInitializers", the extension loads as expected.

How to replicate:
dotnet new browserext
dotnet add package Microsoft.Fast.Components.FluentUI
dotnet build
then load unpacked into Microsoft Edge

I suspect this is similar to #43, but I do not understand the architecture of this project well enough to fix it myself without direction. Willing to fix and PR myself once I get a better understanding.

Thanks. Love this project, by the way!

how to debug

Have you tested the debug can work?
image

i tested was not working!

Incomplete instruction on how to add content script

Thank you very much for your work. Everything works until I tried following the instruction to add content script. I get the following error:

The type or namespace name 'IBrowserExtensionEnvironment' could not be found (are you missing a using directive or an assembly reference?)

The error above comes from App.razor, on the line: "@Inject IBrowserExtensionEnvironment BrowserExtensionEnvironment"

ShadowDom

in content scripts some times you would want to have isolated stylesheets, so page's css won't affect your own content script's html. At this point is worth noting that i just read about shadow dom in here: https://stackoverflow.com/a/20241247 and i'm not sure how it works. But will this library support it in any way?

How to use JSInterop in popup.html?

There is a file in wwwroot clipboardCopy.js with content:

window.clipboardCopy = {
    copyText: function (text) {
        navigator.clipboard.writeText(text)
            .catch(function (error) {
                alert(error);
            });
    }
};

line in index.html:

<script src="clipboardCopy.js"></script>

And code in razor.cs file:

 [Inject] IJSRuntime JSRuntime { get; set; }

        private async Task CopyTextToClipboard()
        {
            await JSRuntime.InvokeVoidAsync("clipboardCopy.copyText", Text);
        }

WebAssembly cannot find the file. How to enable JSRuntime or use another approach?

crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
 Unhandled exception rendering component: Could not find 'clipboardCopy.copyText' ('clipboardCopy' was undefined).

manifest.json template (v0.3.8)

Hi,

The template manifest.json file included in nuget package Blazor.BrowserExtension.Build has a typo:

"web_accessible_resources": [
"framework/",
"BrowserExtensionScripts/
",
"WebExtensionScripts/*"
],

This block does not pass the build check for "WebExtensionsScripts/" and raises the following build error:
Manifest item 'web_accessible_resources' must specify "framework/
", "BrowserExtensionScripts/" and "WebExtensionsScripts/".

There is a missing "s" in WebExtensionScripts, expected WebExtensionsScripts

Kind regards.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.