Code Monkey home page Code Monkey logo

ruby-oembed's Introduction

ruby-oembed

Gem Test Coverage Code Climate Coveralls Maintenance

An oEmbed consumer library written in Ruby, letting you easily get embeddable HTML representations of supported web pages, based on their URLs. See oembed.com for more about the protocol.

Installation

gem install ruby-oembed

Get Started

Built-in Providers

The easiest way to use this library is to make use of the built-in providers.

OEmbed::Providers.register_all
resource = OEmbed::Providers.get('http://www.youtube.com/watch?v=2BYXBC8WQ5k')
resource.video? #=> true
resource.thumbnail_url #=> "http://i3.ytimg.com/vi/2BYXBC8WQ5k/hqdefault.jpg"
resource.html #=> <<-HTML
  <object width="425" height="344">
    <param name="movie" value="http://www.youtube.com/v/2BYXBC8WQ5k?fs=1"></param>
    <param name="allowFullScreen" value="true"></param>
    <param name="allowscriptaccess" value="always"></param>
    <embed src="http://www.youtube.com/v/2BYXBC8WQ5k?fs=1" type="application/x-shockwave-flash" width="425" height="344" allowscriptaccess="always" allowfullscreen="true"></embed>
  </object>
HTML

Providers requiring an access token

Some built-in providers require authorization in order to work. These providers won't be registered unless an access token is provided. You can either pass access tokens to the register_app method.

OEmbed::Providers.register_all(access_tokens: { facebook: @my_facebook_token })

Or you can provide access tokens via environment variable

ENV['OEMBED_FACEBOOK_TOKEN'] #=> 'my-access-token'
OEmbed::Providers.register_all

Currently supported access tokens

access_token environment variable Associated Providers
:facebook OEMBED_FACEBOOK_TOKEN FacebookPost, FacebookVideo, Instagram

Custom Providers

If you'd like to use a provider that isn't included in the library, it's easy to create one. Just provide the oEmbed API endpoint and URL scheme(s).

my_provider = OEmbed::Provider.new("http://my.cool-service.com/api/oembed_endpoint.{format}")
my_provider << "http://*.cool-service.com/image/*"
my_provider << "http://*.cool-service.com/video/*"

You can then use your new custom provider or you can register it along with the rest of the built-in providers.

resource = my_provider.get("http://a.cool-service.com/video/1") #=> OEmbed::Response
resource.provider.name #=> "My Cool Service"

OEmbed::Providers.register(my_provider)
resource = OEmbed::Providers.get("http://a.cool-service.com/video/2") #=> OEmbed::Response

Fallback Providers

Last but not least, ruby-oembed supports Noembed, Embedly, provider discovery. The first two are provider aggregators. Each supports a wide array of websites ranging from Amazon.com to xkcd. The later is part of the oEmbed specification that allows websites to advertise support for the oEmbed protocol.

OEmbed::Providers.register_fallback(
  OEmbed::ProviderDiscovery,
  OEmbed::Providers::Noembed
)
OEmbed::Providers.get('https://www.xkcd.com/802/') #=> OEmbed::Response

Formatters

This library works wonderfully on its own, but can get a speed boost by using 3rd party libraries to parse oEmbed data. To use a 3rd party Formatter, just be sure to require the library before ruby-oembed (or include them in your Gemfile before ruby-oembed).

require 'json'
require 'xmlsimple'
require 'oembed'

OEmbed::Formatter::JSON.backend #=> OEmbed::Formatter::JSON::Backends::JSONGem
OEmbed::Formatter::XML.backend  #=> OEmbed::Formatter::XML::Backends::XmlSimple

The following, optional, backends are currently supported:

Lend a Hand

Code for the ruby-oembed library is hosted on GitHub.

# Get the code.
git clone git://github.com/ruby-oembed/ruby-oembed.git
cd ruby-oembed
# Install all development-related gems.
gem install bundler
bundle install
# Run the tests.
bundle exec rake
# or run the test continually
bundle exec guard

If you encounter any bug, feel free to create an Issue.

We gladly accept pull requests! Just fork the library and commit your changes along with relevant tests. Once you're happy with the changes, send a pull request.

We do our best to keep our tests green

Contributors

Thanks to all who have made contributions to this gem, both large and small.

License

This code is free to use under the terms of the MIT license.

ruby-oembed's People

Contributors

alexey1100 avatar bradleypriest avatar chrisrbnelson avatar cryptic-mystic avatar elektronaut avatar fauno avatar flaburgan avatar florianguenther avatar francois2metz avatar graaff avatar hmans avatar hypomodern avatar ianks avatar javan avatar jhass avatar judofyr avatar kpricorn avatar kyleslattery avatar metavida avatar nogweii avatar papes1ns avatar ramsey avatar raven24 avatar rossta avatar satori avatar slowernet avatar strax avatar taf2 avatar thomsbg avatar voidfiles 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

ruby-oembed's Issues

If the embedly-ruby gem is installed, the Embedly provider should use it to make ruby-oembed more awesome!

The ruby-oembed gem doesn't have to be in competition with Embedly's embedly-ruby gem. If the embedly-ruby gem is loaded, ruby-oembed should detect it and use a specialized OEmbed::Providers::Embedly Class that uses the embedly-ruby gem internally. There are several advantages to this setup.

  1. Because we use the embedly-ruby gem the list of supported URLs will never be out of date.
  2. Because we use ruby-oembed calling OEmbed::Providers.get can resolve oEmbed URLs that aren't registered with Embedly (perhaps because they're private) along side every other oEmbed URL that is supported by Embedly.

No embeddable content error

I want to use Ted as provider. Here is my code in controller

ted = OEmbed::Provider.new("http://www.ted.com/talks/oembed.json")
ted << "http://ted.com/talks/*"
resource = ted.get("http://www.ted.com/talks/dawn_landes_a_song_for_my_hero_the_woman_who_rowed_into_a_hurricane")

But it returns "No embeddable contet at ใ€œ"
Whant is wrong?

undefined method use_ssl

While trying to use ruby-oembed 0.8.8 with jekyll 0.12.1 and https://gist.github.com/vanto/1455726 (all with ruby 1.8), I had to add require 'net/https' to lib/oembed.rb to get it to work.
The error I received was:

Liquid Exception: undefined method `use_ssl=' for #<Net::HTTP www.flickr.com:80 open=false> in index.html

Not working with HTTPS

Hello,

i'm currently running a website in HTTPS and i can't make your gem work.
Indeed, here is the iframe returned by ruby-oembed :

<iframe width="480" height="270" src="http://www.youtube.com/embed/uEDboHDSU50?feature=oembed" frameborder="0" allowfullscreen=""></iframe>

As you can see it's an http youtube url, so it's blocked by my browser.

I tester in my initialiser doing :

require "oembed"
OEmbed::Providers.register_all(:https)

It didn't worked
Then i tried creating a new provider:

require "oembed"

OEmbed::Providers.register_all(:https)
my_youtube_provider = OEmbed::Provider.new("https://www.youtube.com/oembed/")
my_youtube_provider << "http://.youtube.com/"
my_youtube_provider << "https://.youtube.com/"
OEmbed::Providers.unregister(OEmbed::Providers::Youtube)
OEmbed::Providers.register(my_youtube_provider)

It didn't worked neither.

Here is the response i get from OEmbed::Providers.get(article.video_url)

OEmbed::Response::Video:0x37bf4e0 @fields={"html"=>"<iframe width="480" height="270" src="http://www.youtube.com/embed/uEDboHDSU50?feature=oembed\" frameborder="0" allowfullscreen></iframe>", "title"=>"Armenian Duduk on Yanni Live! The Concert Event", "type"=>"video", "thumbnail_url"=>"http://i1.ytimg.com/vi/uEDboHDSU50/hqdefault.jpg", "thumbnail_width"=>480, "author_name"=>"George Kapoyan", "provider_url"=>"http://www.youtube.com/", "thumbnail_height"=>360, "height"=>270, "provider_name"=>"YouTube", "author_url"=>"http://www.youtube.com/user/AlcatrazT2", "width"=>480, "version"=>"1.0"}, @Provider=#OEmbed::Provider:0x71d1c98 @endpoint="https://www.youtube.com/oembed/", @urls=[/^http://([^.]+.)?youtube.com/(.?)/, /^https://([^.]+.)?youtube.com/(.?)/], @Format="json", @request_url="https://www.youtube.com/watch?v=uEDboHDSU50", @Format="json"

Have you any ideas how i could make it returning an https url?

1.0 Roadmap

Hi @metavida! Just came across the project, and it looks great!

Since the readme says the 1.0 is under works, I am wondering if I could get a sense of what are the big parts that you are thinking for the 1.0? And if you had a sense of how far out that might be?

Thank you for your work on this!

copy/pasted youtube url not working

I suppose it should be possible for people to be able to use the youtube link they see in the browser for copy&pasting. E.g.

http://www.youtube.com/watch?feature=player_embedded&v=SUTBdArjxFo

yields the following error:

$> OEmbed::Providers.get "http://www.youtube.com/watch?feature=player_embedded&v=SUTBdArjxFo"
OEmbed::NotFound: No embeddable content at 'http://www.youtube.com/watch?feature=player_embedded&v=SUTBdArjxFo'
        from /home/florian/.rvm/gems/ruby-1.9.2-p290@diaspora/gems/ruby-oembed-0.8.7/lib/oembed/provider.rb:149:in `raw'
        from /home/florian/.rvm/gems/ruby-1.9.2-p290@diaspora/gems/ruby-oembed-0.8.7/lib/oembed/provider.rb:84:in `get'
        from /home/florian/.rvm/gems/ruby-1.9.2-p290@diaspora/gems/ruby-oembed-0.8.7/lib/oembed/providers.rb:102:in `get'
        from (irb):4
        from /home/florian/.rvm/gems/ruby-1.9.2-p290@diaspora/gems/railties-3.1.4/lib/rails/commands/console.rb:45:in `start'
        from /home/florian/.rvm/gems/ruby-1.9.2-p290@diaspora/gems/railties-3.1.4/lib/rails/commands/console.rb:8:in `start'
        from /home/florian/.rvm/gems/ruby-1.9.2-p290@diaspora/gems/railties-3.1.4/lib/rails/commands.rb:40:in `<top (required)>'
        from script/rails:6:in `require'
        from script/rails:6:in `<main>'

I'm not sure if this is a limitation by the Youtube oEmbed API or something else...
(This issue originally came up here: diaspora/diaspora#3025 )

rubygem

Is there any reason why this isn't available as a rubygem on gemcutter?

Upgrading to version 0.14.0 results in undefined method `urls' for OEmbed::Providers::Instagram:Class

We register providers in an initializer as follows:

OEmbed::Providers.register(OEmbed::Providers::Youtube,
                           OEmbed::Providers::Vimeo,
                           OEmbed::Providers::Flickr,
                           OEmbed::Providers::Instagram,
                           OEmbed::Providers::SoundCloud)

After upgrading this gem to 0.14.0 the Rails server won't boot anymore. Inspecting the providers array gives:

[#<OEmbed::Provider:0x00007fdfd6b83518
  @endpoint="https://www.youtube.com/oembed?scheme=https",
  @format="json",
  @urls=
   [/^http:\/\/([^\.]+\.)?youtube\.com\/(.*?)/, /^https:\/\/([^\.]+\.)?youtube\.com\/(.*?)/, /^http:\/\/([^\.]+\.)?youtu\.be\/(.*?)/, /^https:\/\/([^\.]+\.)?youtu\.be\/(.*?)/]>,
 #<OEmbed::Provider:0x00007fdfd84c15e8
  @endpoint="https://vimeo.com/api/oembed.{format}",
  @format="json",
  @urls=[/^http:\/\/([^\.]+\.)?vimeo\.com\/(.*?)/, /^https:\/\/([^\.]+\.)?vimeo\.com\/(.*?)/]>,
 #<OEmbed::Provider:0x00007fdfdcfc14f8
  @endpoint="https://www.flickr.com/services/oembed/",
  @format="json",
  @urls=[/^http:\/\/([^\.]+\.)?flickr\.com\/(.*?)/, /^https:\/\/([^\.]+\.)?flickr\.com\/(.*?)/, /^http:\/\/flic\.kr\/(.*?)/, /^https:\/\/flic\.kr\/(.*?)/]>,
 OEmbed::Providers::Instagram,
 #<OEmbed::Provider:0x00007fdfdf185030
  @endpoint="https://soundcloud.com/oembed",
  @format=:json,
  @urls=[/^http:\/\/([^\.]+\.)?soundcloud\.com\/(.*?)/, /^https:\/\/([^\.]+\.)?soundcloud\.com\/(.*?)/]>,
 #<OEmbed::Provider:0x00007fdfd6bfc260
  @endpoint="https://web.microsoftstream.com/oembed/",
  @format="json",
  @urls=[/^https:\/\/([^\.]+\.)?microsoftstream\.com\/video\/(.*?)/, /^https:\/\/([^\.]+\.)?microsoftstream\.com\/channel\/(.*?)/]>]

After which an undefined method 'urls' for OEmbed::Providers::Instagram:Class is thrown

ProviderDiscovery does not work for WordPress

The line of WordPress pages are not parsed correcty, I think.
It states:
<link rel="alternate" type="application/json+oembed" href="http://public-api.wordpress.com/oembed/1.0/?format=json&amp;url=https%3A%2F%2Fsweetandweak.wordpress.com%2F2011%2F09%2F23%2Fnothing-starts-the-morning-like-a-good-dose-of-panic%2F&amp;for=wpcom-auto-discovery"><link rel="alternate" type="application/xml+oembed" href="http://public-api.wordpress.com/oembed/1.0/?format=xml&amp;url=https%3A%2F%2Fsweetandweak.wordpress.com%2F2011%2F09%2F23%2Fnothing-starts-the-morning-like-a-good-dose-of-panic%2F&amp;for=wpcom-auto-discovery">

probably you just have to say
provider_endpoint ||= /<link.*href=['"]*([^\s'"]+)['"]*.*application\/json\+oembed.*>/.match(res.body)[0]
instead of
provider_endpoint ||= /<link.*href=['"]*([^\s'"]+)['"]*.*application\/json\+oembed.*>/.match(res.body)
in these lines: https://github.com/judofyr/ruby-oembed/blob/master/lib/oembed/provider_discovery.rb#L41

Implement testing using the vcr gem

While mocking out HTTP requests manually has worked so far, the VCR gem lets you "record your test suite's HTTP interactions and replay them during future test runs for fast, deterministic, accurate tests." This sounds like a perfect fit for this project.

Move all OEmbed::Providers methods to the OEmbed class

I was just thinking, wouldn't it be nice if you could just call OEmbed.get(@my_url)? We can keep the OEmbed::Providers Class around for backwards compatibility, but can anyone think of a good reason to avoid the shorter syntax?

Additional headers on request?

Hi. Is it possible to send additional headers on the request?

I needed to add a Referer header to get additional information from private videos on Vimeo.

Add support for more XML and JSON parsing libraries

The ruby-oembed gem currently relies on the xml-simple and json gems. It should allow for other parsing libraries to be either detected or specified. Libraries we should support:

XML

  • Hpricot
  • Nokogiri

JSON

  • Rails 3 JSON

Sugest even more in the comments.

YouTube no longer responds with xml or json body on private videos

Stumbled upon this behaviour via a Drupal bug report but this is slightly different: I was hunting down a OEmbed::ParseError which is probably rooted in a change on YouTubes side: From what I can tell from my own testing, YouTube will no longer respond with a formatted body to oembed requests for private videos.

I tested with https://www.youtube.com/oembed/?scheme=https&url=https://www.youtube.com/watch?v=ejCiG0swM24&format=json which will now respond with just Forbidden as body text (and HTTP 200 ๐Ÿ˜–)

Screenshot-2020-12-19-203412

Whereas existing videos can be embedded just fine, since they will responde in their proper format, e.g. https://www.youtube.com/oembed/?scheme=https&url=https://www.youtube.com/watch?v=MPY_EuvimH0&format=json

Screenshot-2020-12-19-203423


I am not sure where to go from here. As far as I understand the spec, responses should be either valid json or xml and even the HTTP response doesn't give any hints on the failure mode. ๐Ÿ˜Ÿ

Let me know if I can help to debug this further.

HTTPS not supported

Hi,

you project is really awesome, we are using it for Diaspora.

But since all our pages are encrypted (HTTPS) we rely on oEmbed content (iframes) that also use the HTTPS protocol (otherwise you get security warnings in your browser).

Vimeo only returns https-iframes if you use https://vimeo.com/api/oembed.{format} as endpoint instead of http://www.vimeo.com/api/oembed.{format} (you even have to remove the 'www.', don't ask my why!)
When you use an https endpoint, your code does not work, because you need to setup Net::HTTP correctly to use HTTPS. (ruby-oembed thows an 'end of file reached' error)
It would be amazing if this issue could be fixed in your gem.

Cheers,

Manuel

RFC allow client to specify embedded content URI scheme

Problem

Some oEmbed providers respond with HTTPS embeded content only when the oEmbed API endpoint is requested over HTTPS. For example, Vimeo:
embeded content over http vs. embeded content over https.
When presenting site content and embeded content together, it's important to use the the same protocol (either HTTP or HTTPS) otherwise mixed content warnings occur in most browsers.
At the moment, ruby-oembed associates a URL with an oEmbed API provider endpoint but does not allow the client application to specify the embeded content URI scheme.

Potential Solution

Register OEmbed::Provider with a :scheme flag and optionally pass a flag to OEmbed::Providers#find and OEmbed::Providers#get, e.g:

vimeo_ssl = OEmbed::Provider.new("https://vimeo.com/api/oembed.{format}") 
vimeo_ssl << "http://*.vimeo.com/*"  
vimeo_ssl << "https://*.vimeo.com/*"
OEmbed::Providers.register(vimeo_ssl, :scheme => 'https')
OEmbed::Providers.find('http://vimeo.com/17472698', :scheme => 'https')
OEmbed::Providers.get('http://vimeo.com/17472698', :scheme => 'https')

when scheme is omitted, the default provider (e.g. provider registered without scheme) should be selected. It should be possible to extend the library with this functionality without breaking backwards compatibility.

OEmbed::Formatter::JSON.backend::ParseError is nil

For some reason ::ActiveSupport::JSON.parse_error is nil at the point where it is assigned to OEmbed::Formatter::JSON.backend::ParseError and thus you get strange exceptions later. I use Rails 2.3.

Maybe it would be better to change it to a method that reads ::ActiveSupport::JSON.parse_error whenever it is called?

Currently I fix this by adding this initializer:
module OEmbed
module Formatter
module JSON
module Backends
module ActiveSupportJSON
if ParseError.nil?
remove_const(:ParseError)
if ::ActiveSupport::JSON.parse_error.nil?
ParseError = StandardError
else
ParseError = ::ActiveSupport::JSON.parse_error
end
end
end
end
end
end
end

Incompatible with Ruby 2.2

Run the following code in 2.1.x and 2.2.

require 'rubygems'
require 'openssl'
require 'oembed'

provider = OEmbed::Providers::Vimeo.get("http://vimeo.com/113057654")
puts provider.html

In Ruby 2.1.4, I get successful HTML output:

"<iframe src=\"//player.vimeo.com/video/113057654\" width=\"1280\" height=\"720\" frameborder=\"0\" title=\"Gingerbread House 2014\" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>"

In Ruby 2.2.0, I get this error:

/Users/j/.rbenv/versions/2.2.0/lib/ruby/2.2.0/uri/generic.rb:743:in `registry=': can not set registry (URI::InvalidURIError)
    from /Users/j/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/ruby-oembed-0.8.11/lib/oembed/provider.rb:138:in `block in raw'
    from /Users/j/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/ruby-oembed-0.8.11/lib/oembed/provider.rb:138:in `each'
    from /Users/j/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/ruby-oembed-0.8.11/lib/oembed/provider.rb:138:in `raw'
    from /Users/j/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/ruby-oembed-0.8.11/lib/oembed/provider.rb:86:in `get'
    from /Users/j/Desktop/ruby-oembed-test.rb:5:in `<main>'

Embedly deprecating free tier

Embedly is removing the free tier for their API.

What is the opinion of this library in regards to paid aggregators? The library heavily relies on Embedly and the deadline for their API transition is April 17th.

The announcement can be found here.

OEmbed::Providers.register_all() does not register all provided providers

Currently, register_all is defined as follows:

def register_all
  register(Youtube, Flickr, Viddler, Qik, Revision3, Hulu, Vimeo)
end

The following providers are defined in the same file but are not registered:

  • Instagram
  • Slideshare
  • Yfrog
  • MlgTv

I guess they should be included so I suggest to simply add them to the register_all method, e.g. like this:

def register_all
  register(Youtube, Flickr, Viddler, Qik, Revision3, Hulu, Vimeo, 
           Instagram, Slideshare, Yfrog, MlgTv)
end

how do i use embedly with this?

The ReadMe states that ruby-oembed supports embedly to get a long list of additional providers, but I don't see any documentation on how to do this. Once I've bundled and required the 'embedly' gem, do I need to register somehow with the embedly library?

do I just do OEmbed::Providers.register(OEmbed::Providers::Foo) for the providers I need?

Test and improve oEmbed discovery

I implemented oEmbed discovery as a "fallback" Provider but didn't have a chance to really flesh out the tests and ultimately think the whole process of setting a fallback_provider to be a bit obtuse. (e.g. Is Embedly a fallback provider or not?) First person to resolve these issues get serious kudos!

Create a rake task to grab updated URL pattens from Embedly

Embedly offers an awesome API that lists all of its recognized URL pattens in a single JSON file. There should be a rake task (for developers to run) that:

  1. Downloads the JSON file from Embedly
  2. Stores it as a sorted YAML or flat txt file so that changes are easy to spot in git & the gem works even if the end user only has XML support (a rare case, I admit)

Server does not start after plugin installation (Rails 3)

Hi there,

The plugin works great in Rails 2.3.5 but today I tested it in Rails 3.0.0.beta and the server would not start after the installation. It complains with the following message: 'OEmbed::FormatNotSupported' format (OEmbed::FormatNotSupported).

I tried to fix it and think I found the problem. Once the JSON gem is installed it seems to work fine. I don't know why this is... maybe the plugin doesn't work with the build in JSON stuff in Rails 3?

I added a short step-by-step guide to the wiki with installation instructions for Rails 3.

Thanks!

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.