Giter VIP home page Giter VIP logo

style9's Introduction

style9

CSS-in-JS compiler inspired by Meta's StyleX, with near-zero runtime, atomic CSS extraction and TypeScript support. Framework agnostic.

Note

StyleX was open-sourced on 2023-12-5. Consider using that instead

Basic usage

For a complete walkthrough of the API, see Usage guide.

import style9 from 'style9';

const styles = style9.create({
  blue: {
    color: 'blue',
  },
  red: {
    color: 'red'
  }
});

document.body.className = styles('blue', isRed && 'red');

For the above input, the compiler will generate the following output:

/* JavaScript */
document.body.className = isRed ? 'cRCRUH ' : 'hxxstI ';

/* CSS */
.hxxstI { color: blue }
.cRCRUH { color: red }

Installation

# Yarn
yarn add style9

# npm
npm install style9

Compiler setup - required

The following is the minimally required Webpack setup for extracting styles to a CSS file. For Webpack options and Rollup, Next.js, Gatsby,Vite, and Babel plugins, see Bundler plugins.

const Style9Plugin = require('style9/webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  // Collect all styles in a single file - required
  optimization: {
    splitChunks: {
      cacheGroups: {
        styles: {
          name: 'styles',
          type: 'css/mini-extract',
          // For webpack@4 remove type and uncomment the line below
          // test: /\.css$/,
          chunks: 'all',
          enforce: true,
        }
      }
    }
  },
  module: {
    rules: [
      {
        test: /\.(tsx|ts|js|mjs|jsx)$/,
        use: Style9Plugin.loader,
      },
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, 'css-loader']
      }
    ]
  },
  plugins: [
    new Style9Plugin(),
    new MiniCssExtractPlugin()
  ]
};

Documentation

  1. Background
  2. Usage guide
  3. Bundler plugins
  4. TypeScript
  5. Ecosystem
  6. How it works
  7. FAQ
  8. Example apps

Have a question?

Look at the FAQ, search the repo, or ask in discussions.

style9's People

Contributors

beiyanyunyi avatar bsouthga avatar dpeek avatar gatzjames avatar johanholmerin avatar mitchpierias avatar myamolane avatar nonalgebraic avatar nonzzz avatar sukkaw avatar txhawks 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

style9's Issues

[Feature Request]: Support Vite

Background

It's a amazing project, I using it in my project. But when i migrate to vite. I found style9 currently don't support it. So i want a vite plugin :)

Others

I'll do it.

Feature request: support nested selectors

I'd like to have a way to specify rules for nested selectors, like:

style9.create({
  text: {
    color: '#333',
    '&>a': {
      color: 'blue',
    }
  },
});

Admittedly, this doesn't fit very well with the concept of atomic CSS. However, it is often a critical escape hatch in cases where we do not have control over the html, e.g., when dealing with text generated from markdown or wyiwg editors, and all other atomic-styling solutions I'm aware of support this feature to some degree.

Plugin does not work with next-contentlayer

style9/next does not seem to work nice with next-contentlayer. When the two plugins are used together, an error is thrown:

Syntax error: Support for the experimental syntax 'importAssertions' isn't currently enabled (3:43):
// next.config.js
const { withContentlayer } = require("next-contentlayer");
const withTM = require("next-transpile-modules")(["style9"]);
const withStyle9 = require("style9/next");

const nextConfig = withContentlayer({
  ...withStyle9()(withTM()),
});
module.exports = nextConfig;

# or
module.exports = withTM(withStyle9({})(withContentlayer({})));

# or 
module.exports = {
  ...withContentlayer(),
  ...withStyle9()(withTM()),
};

# or
function compose(...plugins) {
  return (options) => {
    return plugins.reduce((acc, next) => {
      return next(acc);
    }, options);
  };
}

module.exports = compose(
  withContentlayer,
  withStyle9(),
  withTM
)()

# or
module.exports = withStyle9()(compose(
  withContentlayer,
  withTM
)())

I have tried many solutions, all to no avail.

Unclear behavior when using conditionals

There seems to be some weird behavior going on when using conditionals.

Given these styles

const styles = style9.create({
  primaryButton: {
    ":hover": {
      boxShadow: "var(--box-shadow-hover)"
    }
  },
  secondaryButton: {
    ":hover": {
      boxShadow: "var(--box-shadow-hover)"
    }
  },
});

I would expect these two invocations to return the same string

const st1 = styles(
      true && 'primaryButton',
      false && 'secondaryButton'
  );
  const st2 = styles(
      true && 'primaryButton'
  );

// st1 === st2 => false

// st1 === "" => true

// st2 === "c17j9v3m " => true

Official support for CRA

Per your suggestion in #2 (comment) , I tried adding style9 to CRA via CRACO (my craco config is included below). The only changes I made are adding the Style9Plugin.loader and new Style9Plugin().

This works entirely fine in development. However, there's an interesting glitch where the order of CSS rules changes in production leading to glitches like the one below (a minimal button displays as a regular button in light mode, but correctly as a minimal button in dark mode).

chrome_mrAlyn3s6C.mp4

This demo app does not use style9 calls anywhere. I've only simply added the config in craco. The issue goes away when I remove new Style9Plugin() from the plugins list. So I assume the Style9Plugin (or perhaps the postcss loader it calls) are modifying CSS incorrectly somehow.

Part of the issue here could well be my very limited understanding of webpack, their plugins, etc. It would be a great help to have a clean CRA plugin supported by the library.

I'm happy to share my repro if it would be helpful.

How to use global styles?

em outras bibliotecas eu posso usar estilos globais... como eu devo fazer nessa biblioteca para fazer um reset css por exemplo?

selector parse error

I found that style9 will try to parse selector name from each decl's parent
https://github.com/johanholmerin/style9/blob/master/src/process-css.js#L94
const selectors = parseSelector(rule.parent);

but there are some exception, like this one
@-ms-viewport { width: device-width; }
PostCSS recognizes width: device-width as a declaration, but the type of this declarationโ€™s parent is 'atrule'. There is no property 'selector' in type 'atrule', and this will make postcss-selector-parser generate exception.

As far as I know, @-ms-viewport is a deprecated API but some UI component repository still use it for some reasons.

[webpack-cli] TypeError: Cannot read property 'valueOf' of undefined at tokenize (/Users/cosimo/code/style9/node_modules/postcss-selector-parser/dist/tokenize.js:93:23) at new Parser (/Users/cosimo/code/style9/node_modules/postcss-selector-parser/dist/parser.js:130:41) at Processor._root (/Users/cosimo/code/style9/node_modules/postcss-selector-parser/dist/processor.js:55:18) at Processor._runSync (/Users/cosimo/code/style9/node_modules/postcss-selector-parser/dist/processor.js:102:21) at Processor.transformSync (/Users/cosimo/code/style9/node_modules/postcss-selector-parser/dist/processor.js:173:17) at parseSelector (/Users/cosimo/code/style9/src/process-css.js:41:47) at /Users/cosimo/code/style9/src/process-css.js:94:23 at Array.forEach (<anonymous>) at extractDecls (/Users/cosimo/code/style9/src/process-css.js:93:9) at sortPseudo (/Users/cosimo/code/style9/src/process-css.js:149:27) at LazyResult.run (/Users/cosimo/code/style9/node_modules/postcss/lib/lazy-result.js:288:14) at LazyResult.sync (/Users/cosimo/code/style9/node_modules/postcss/lib/lazy-result.js:274:26) at LazyResult.stringify (/Users/cosimo/code/style9/node_modules/postcss/lib/lazy-result.js:298:10) at LazyResult.get (/Users/cosimo/code/style9/node_modules/postcss/lib/lazy-result.js:379:19) at Style9Plugin._processFiles (/Users/cosimo/code/style9/webpack/index.js:52:18) at /Users/cosimo/code/style9/webpack/index.js:33:16

Missing css properties

Hello!
Awesome library, just trying it out. Just noticed that not all css properties is supported, like listStyle and borderTopStyle. How to fix that?

EDIT

Looks like background doesn't work either, or am I doing something wrong here?
image

Issue with webpack plugin on windows

I guess I must be the only person writing code on windows :)

modules by path ./Application/ 2.22 KiB
      no extension
        Field 'browser' doesn't contain a valid alias configuration
        C:\Source\_\Application\Root.KBftMHg.css doesn't exist
      .tsx
        Field 'browser' doesn't contain a valid alias configuration
        C:\Source\_\Application\Root.KBftMHg.css.tsx doesn't exist
      .ts
        Field 'browser' doesn't contain a valid alias configuration
        C:\Source\_\Application\Root.KBftMHg.css.ts doesn't exist
      .js
        Field 'browser' doesn't contain a valid alias configuration
        C:\Source\_\Application\Root.KBftMHg.css.js doesn't exist
      as directory
        C:\Source\_\Application\Root.KBftMHg.css doesn't exist
 @ ./Application/app.web.tsx 4:0-26 5:162-166

I have traced the issue down to loader.js:43 where the value of css path is 'C:/Source/_/Application/Root.KBftMHg.css', that is with forward slashes instead of backslashes

I'm not really sure the best fix otherwise I'd have sent through a PR.. it seems deliberate in https://github.com/webpack/loader-utils/blob/master/lib/interpolateName.js#L44

For now, I'm just writing both paths:

virtualModules.writeModule(cssPath.replace(/\//g, "\\"), metadata.style9);
virtualModules.writeModule(cssPath, metadata.style9);

Add support for pseudo selectors and media queries

Example from Facebook Workplace:

{
  focused: {
    outline: "2px solid Highlight",
    "@media (-webkit-min-device-pixel-ratio: 0)": {
        outline: "5px auto -webkit-focus-ring-color"
    }
  },
  unfocused: {
    outline: "none"
  }
}

{
  typeaheadLayoutOpened: {
    borderBottomEndRadius: "8px",
    borderBottomStartRadius: "8px",
    "::before": {
      borderBottomEndRadius: "8px",
      borderBottomStartRadius: "8px"
    }
  }
}

transitionProperty with multiple values doesn't produce valid CSS

Currently the transitionProperty doesn't work when providing an array of properties.
e.g.

let styles = style9.create({
  default: {
    transitionProperty: ["backgroundColor", "color"]
  }
});

the resulting class will end up with this css:

.random-name {
  transition-property: backgroundColor color;
}

where it should be a comma separated hyphen-case string:

.random-name {
  transition-property: background-color, color;
}

For now a workaround would be to provide the values as a string:

let styles = style9.create({
  default: {
    transitionProperty: "backgroundColor, color"
  }
});

Support for Preact CLI

Hi @johanholmerin!
Very promising lib! I was eager to pull it in my preact project, however I am having some hard time figuring out how to wire it into preact-cli.

I tried to follow your guides in the Readme's webpack section, and even the vue-related example that you prepared, without much luck.

The conversion to atomic classnames seemed to be working, as they were written onto the target element in the DOM, but I was missing the actual related CSS output. I am not sure whether it is related to how preact-cli assembles the final loaders for webpack, where it seemes to be using style-loader instead of css-loader and maybe even MiniCssExtractPlugin.

I tried with something like this:

// preact.config.js

import Style9Plugin from 'style9/webpack';

export default {
  webpack(config, env, helpers, options) {
  // ...
    config.module.rules.splice(4, 0, {
      test: /\.(tsx|ts|js|mjs|jsx)$/,
      use: Style9Plugin.loader
    });

    config.plugins.splice(8, 0, new Style9Plugin());
  }
};

Could you give some hints on pulling style9 into a preact project?

Next.js hot-reload not working for new styles

Using the withStyle9 plugin, hot-reload only sort of works: When authoring styles, classes will correctly be attached to elements on hot-reload, but a new css file isn't generated, so if the class did not previously exist already, no style is associated with the attached class. A hard reload fixes this.

So, for example, if we have:

const styles = style9.create({
  foo: {
    color: '#333',
    display: 'flex',
   paddingLeft: '2em',
   paddingRight: '2em',
  },
   bar: {
     marginTop: '2em',
   },
});

And we than add paddingLeft: 2em to bar, that will work fine, because there is already a class associated with paddingLeft: 2em in the css file. However, if we were to add, for instance, color: 'green', to either foo or bar, a new class would be attached to the relevant element(s), but it would have no effect, because there is no class associated with that style already in the css file, and no new css file is being generated.

[Feature Request] Transpile away `style9` runtime call

Facebook's stylex has evolved a lot since it is being first introduced in React Conf 2019. At the time, stylex uses a syntax like this:

const styles = stylex.create({ red });

<div className={styles('red')} />

Nowadays, stylex seems to prefer the syntax with directly stylex() call, see React Finland 2021 - Introducing StyleX:

const styles = stylex.create({ red });

<div className={stylesx(styles.red)} />

And according to React Finland 2021, they are able to strip most of stylex runtime call through static analysis.

Currently, style9 doesn't support stripping away the style9() runtime at all. I am about to experiment with it a little bit to see if it is doable.

Incompatible with Vite bundler

Vite does not process files during development. It serves application source using browser built-in support for JavaScript modules.

This leads to style9 failing in runtime:

Uncaught Error: style9.create calls should be compiled away

Possibility to write css as template literal

๐Ÿ‘‹ Hey, is it possible to add a way to write css as template literals?

Simple example:

import stylesheet from 'style9'

const styles = stylesheet`
  .one {
    color: red;
  }
`

console.log('my class', styles('one'))

Incompatible with latest version of Next.js

When using the latest version of next, the following error is thrown:

./pages/index.22C1ZZc.css:4:0
Module not found:
  Can't resolve '[...]/node_modules/next/dist/compiled/mini-css-extract-plugin/hmr/hotModuleReplacement.js'
null

Here's a basic reproduction reproduction repository: TxHawks/style9-latest-next-repro
The 1st commit is a working example using Next v10.0.9
The 2nd commit breaks after an upgrade to latest Next (v10.2.3)
The 3rd commit remains broken after upgrading next-transpile-modules to its latest version (v7.2.0)

Webpack Example

I know that this is not the ideal place for this... I'm having trouble running a webpack with babel-loader. Would you have a more complete example of a configured webpack? I was not successful, following the documentation.

My webpack:

module.exports = (env = { NODE_ENV: 'development' }) => {
  const prod = env.NODE_ENV === 'production';

  // eslint-disable-next-line no-console
  console.log(`MODE: ${prod ? 'PRODUCTION' : 'DEVELOPMENT'}`);

  return {
    entry: './src/index.tsx',
    output: {
      filename: '[name].[chunkhash].js',
      path: path.resolve(__dirname, 'dist'),
    },
    mode: prod ? 'production' : 'development',
    devtool: 'source-map',
    ...(prod
      ? {}
      : { devServer: { historyApiFallback: true, hot: true, hotOnly: true } }),
    plugins: [
      // HTML Template
      new HtmlWebpackPlugin({ template: './index.html' }),
      new Style9Plugin(),
      new MiniCssExtractPlugin(),
    ].filter(Boolean),
    resolve: {
      extensions: ['.tsx', '.ts', '.js'],
    },
    module: {
      rules: [
        {
          test: /\.([tj])sx?$/,
          use: [
            Style9Plugin.loader,
            {
              loader: 'babel-loader',
              options: {
                presets: [
                  ['@babel/preset-env', { targets: 'last 1 chrome version' }],
                  [
                    '@babel/preset-react',
                    {
                      // Removes the need to import React into JSX files
                      runtime: 'automatic',
                    },
                  ],
                  '@babel/preset-typescript',
                ],
                plugins: [
                  // Fast Refresh
                  !prod && require.resolve('react-refresh/babel'),
                ].filter(Boolean),
                cacheDirectory: true,
              },
            },
          ],
        },
        {
          test: /\.css$/i,
          use: [MiniCssExtractPlugin.loader, 'css-loader'],
        },
        {
          test: /\.(png|jpe?g|gif|woff2?|eot|otf|webp)$/i,
          use: 'file-loader',
        },
      ],
    },
  };
};

Error:

Captura de Tela 2020-12-28 aฬ€s 22 30 14

Multiple Transition Effects

Is it currently possible specify multiple transition effects? From what I can tell the transition sub-properties only accept a string, not an array.

How to define css variables?

Hi Johan,
thank you so much for open-sourcing this library!

I'm using typescript and it complains about my CSS variables not existing on type "Style". At runtime it works fine though.
What's the recommended way of defining these variables?

const styles = style9.create({
  body: {
    margin: 0
  },
  lightTheme: {
    "--bg-color": "#CCC"
  }
});

Atomic css rule not works when component loaded as lazy

If You have a component something like this:

import style9 from 'style9';

const styles = style9.create({
  blue: {
    color: 'blue',
  },
  red: {
    color: 'red'
  }
});

function LazyComponent() {
  return (
    <h1 className={styles('blue', true && 'red')}>I'm Lazy Component</h1>
  );
}

export default LazyComponent;

And before that you created this style in another component:

const styles = style9.create({
  blue: {
    color: 'blue',
  },
  red: {
    color: 'red'
  }
});

New CSS file generated as duplicate

Compress class names

Compressing the generated class names into the shortest possible strings could be a nice optimization.

In jest, my suggestion is to find a way to use incremental strings instead of hashes, e.g., .a, .b, etc., instead of c1r9f2e5, cu2kwdz, etc.

This is the class name strategy used by Fela and currently considered by compiled (relevant RFC).

Compiled from Atlassian

Hi, is there any reason not to combine your efforts with compiled from Atlassian? They support shorthands properties, styled-components and emotion-like API, and much more. CSS extraction is currently being worked on.

Docs: Getting started

Hey @johanholmerin, pretty interesting package, but I've tried to run it in Nextjs applications and I wasn't able, I didn't get which are the exact steps to go with it.

So my suggestion is to improve the documentation and perhaps add some use cases, or even an example, using NextJS, CRA, or whatever.

Support for Vue

Hey, this looks great! I wanted to build something like this myself, but this looks like just what I need. However, I use Vue. Any chance you are going to support it? Seems like it should be doable since Vue let's you modify the webpack config, but Im not sure exactly what I need to modify.

Using imported values inside the create method breaks the Webpack build

Using imported values within the styles object passed to Style9.create() seems to break the Webpack build when using the Style9 Webpack loader.

Steps to reproduce:

  1. Clone this minimal reproduction repo I created: https://github.com/nonAlgebraic/style9-import-bug
  2. Run yarn install
  3. Run yarn build

Expected result

The color value imported from colorValue.js ("blue") is applied to the <body>.

Actual result

The Webpack build fails with an error:

SyntaxError: unknown: Could not evaluate value
  4 | const styles = style9.create({
  5 |   body: {
> 6 |     color: colorValue,
    |            ^^^^^^^^^^
  7 |   },
  8 | });

Incompatible with ejected create-react-app

I tried to use style9 in ejected CRA but it not works.

How reproduce:

Install CRA

npx create-react-app s9 --use-npm

Eject

npm run eject

Add style9 config to

./config/webpack.config.js

Add smaple code to App.js ex:

import style9 from 'style9';

const styles = style9.create({
  blue: {
    color: 'blue',
  },
  red: {
    color: 'red'
  }
});

function App() {
  return (
    <h1 className={styles('blue', true && 'red')>Hi Style9</h1>
  );
}

export default App;

Run

npm run start

grid-area

Possible for an easier implementation for named grid areas? I get that it's a shorthand property for grid-column-end,
grid-column-start, grid-row-end, grid-row-start, and it would be hard to support the non-named version (i.e. something like grid-area: 2 / 1 / 2 / 4;) but expanding named grid-areas would be a boon.

Using Next.js _document.js throws error on static export

I have to use _doucment.tsx in Next.js to add the lang attribute to the html element. And it I keep seeing this error on a static export

ModuleNotFoundError: Module not found: Error: Can't resolve '/Users/eric/projects/airtable-code-interview/pages/index.xsrcSRK.css' in '***/***/airtable-code-interview/pages'

Here's my _document.tsx

import Document, { DocumentContext,Html,Head,Main,NextScript } from 'next/document'

class MyDocument extends Document {
  static async getInitialProps(ctx: DocumentContext) {
    const initialProps = await Document.getInitialProps(ctx)

    return initialProps
  }
  render() {
    return (
      <Html>
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

export default MyDocument

And my index.tsx

import Head from 'next/head'
import style9 from 'style9';

const styles = style9.create({
  container: {
    minHeight: '100vh',
    paddingLeft: '.5rem',
    paddingRight: '.5rem',
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center'
  }
});

export default function Home() {
  return (
    <div className={styles('container')}>
      <Head>
        <title>Create Next App</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main>
        <h1 className="title">
          Welcome to <a href="https://nextjs.org">Next.js!</a>
        </h1>

        <p className="description">
          Get started by editing <code>pages/index.js</code>
        </p>

        <div className="grid">
          <a href="https://nextjs.org/docs" className="card">
            <h3>Documentation &rarr;</h3>
            <p>Find in-depth information about Next.js features and API.</p>
          </a>

          <a href="https://nextjs.org/learn" className="card">
            <h3>Learn &rarr;</h3>
            <p>Learn about Next.js in an interactive course with quizzes!</p>
          </a>

          <a
            href="https://github.com/zeit/next.js/tree/master/examples"
            className="card"
          >
            <h3>Examples &rarr;</h3>
            <p>Discover and deploy boilerplate example Next.js projects.</p>
          </a>

          <a
            href="https://vercel.com/import?filter=next.js&utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
            className="card"
          >
            <h3>Deploy &rarr;</h3>
            <p>
              Instantly deploy your Next.js site to a public URL with Vercel.
            </p>
          </a>
        </div>
      </main>

      <footer>
        <a
          href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
          target="_blank"
          rel="noopener noreferrer"
        >
          Powered by{' '}
          <img src="/vercel.svg" alt="Vercel Logo" className="logo" />
        </a>
      </footer>
    </div>
  )
}
export const config = { unstable_runtimeJS: false }

(unrelated this is a very cool project)

Question: Scoping and Webpack

I just found this repo and I'm excited about it. But I can't quite tell from README if it quite meets my needs. If it does I want to use it / contribute. I'm wondering:

  • It appears that this library has the ability to extract css on build time and put it into a separate CSS file. Is this correct?
  • Are the CSS classes scoped modularly scoped in the same way other CSS-in-JS libraries do?

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.