Coder Social home page Coder Social logo

codejar's Introduction

CodeJar โ€“ an embeddable code editor for the browser

npm npm bundle size

Features

  • Lightweight (2.45 kB only)
  • No dependencies
  • Preserves indentation on a new line
  • Adds closing brackets, quotes
  • Indents line with the Tab key
  • Supports undo/redo

Getting Started

Install CodeJar ๐Ÿฏ ย  via npm:

npm i codejar

Create an element and init the CodeJar ๐Ÿฏ:

<div class="editor"></div>
<script>
  let jar = CodeJar(document.querySelector('.editor'), highlight)
</script>

Second argument to CodeJar is a highlighting function (like Prism.js, highlight.js):

const highlight = (editor: HTMLElement) => {
  const code = editor.textContent
  code = code.replace('foo', '<span style="color: red">foo</span>')
  editor.innerHTML = code
}

const jar = CodeJar(editor, highlight)

Third argument to CodeJar is options:

  • tab: string replaces "tabs" with given string. Default: \t.
    • Note: use css rule tab-size to customize size.
  • indentOn: RegExp allows auto indent rule to be customized. Default /[({\[]$/.
  • moveToNewLine: RegExp checks in extra newline character need to be added. Default /^[)}\]]/.
  • spellcheck: boolean enables spellchecking on the editor. Default false.
  • catchTab: boolean catches Tab keypress events and replaces it with tab string. Default: true.
  • preserveIdent: boolean keeps indent levels on new line. Default true.
  • addClosing: boolean automatically adds closing brackets, quotes. Default true.
  • history records history. Default true.
  • window window object. Default: window.
const options = {
  tab: ' '.repeat(4), // default is '\t'
  indentOn: /[(\[]$/, // default is /{$/
}

const jar = CodeJar(editor, highlight, options)

API

updateCode(string)

Updates the code.

jar.updateCode(`let foo = bar`)

updateOptions(Partial<Options>)

Updates the options.

jar.updateOptions({tab: '\t'})

onUpdate((code: string) => void)

Calls callback on code updates.

jar.onUpdate(code => {
  console.log(code)
})

toString(): string

Return current code.

let code = jar.toString()

save(): string

Saves current cursor position.

let pos = jar.save()

restore(pos: Position)

Restore cursor position.

jar.restore(pos)

recordHistory()

Saves current editor state to history.

destroy()

Removes event listeners from editor.

Related

Become a sponsor

Every line of code in my repositories ๐Ÿ“– signifies my unwavering commitment to open source ๐Ÿ’ก. Your support ๐Ÿค ensures these projects keep thriving, innovating, and benefiting all ๐Ÿ’ผ. If my work has ever resonated ๐ŸŽต or helped you, kindly consider showing love โค๏ธ by sponsoring. ๐Ÿš€ Sponsor Me Today! ๐Ÿš€

License

MIT

codejar's People

Contributors

0xflotus avatar antonmedv avatar aziis98 avatar blunt1337 avatar bytesnz avatar creekmind avatar githubaccount8 avatar gnietschow avatar hgs3 avatar julianpoemp avatar junghoocho avatar lizheming avatar mike76-dev avatar mmulet avatar moderatelyconfused avatar prestonhager avatar robertlyall avatar ryanhaoo avatar strd6 avatar subhendudash02 avatar szepeviktor avatar tchan5217 avatar timwillebrands avatar xyzshantaram avatar zamfofex avatar zazaulola 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  avatar  avatar  avatar  avatar  avatar  avatar

codejar's Issues

Module style not compatible with TypeScript

Hi, first of all let me say that I absolutely love the simplicity and elegance of this lib ๐Ÿ‘

I am using it in a TypeScript project and was surprised to see that, although this is written in TS, it is not readily consumable from a TS project.

The reason is the "revealing module" pattern used for the main CodeJar function. When constructing the function with the new keyword, TypeScript cannot infer the type of the returned object. Additionally, even though CodeJar can be constructed like a class, it is only a value and there is no corresponding CodeJar type, which is rather unexpected for a TypeScript user.

import { CodeJar } from 'codejar';

// ..
let jar: CodeJar;
// TS2749: 'CodeJar' refers to a value, but is being used as a type here.

jar = new CodeJar(element, highlight);
// TS7009: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type

It is possible to get things working with a little bit of TS trickery:

import { CodeJar } from 'codejar';

//..
let jar: ReturnType<typeof CodeJar>;

jar = CodeJar(element, highlight);
// works without "new", and "jar" instance has correct type with auto-complete etc.

Solution

I can see 2 possible solutions:

  1. Add some docs with a TypeScript example (less work, but weirder for TS end-users)
  2. Refactor the CodeJar module function to a regular ES6 class (more work, but results in expected behaviour in TS)

What do you think? I'd be willing to put in a PR for either of the above solutions if you agree.

consider adding optional window parameter to CodeJar()

In order to get CodeJar working inside an iframe, I made the following change to the JavaScript (hopefully this is easy to port back to the TypeScript source):

export function CodeJar(editor, highlight, window = window, opt = {}) {
    let document = window.document;

This adds an optional window parameter, which I can provide the iframe window for, and then all the getSelection() calls work. It also sets document from whatever window is, for the 6 locations CodeJar refers to it.

I was having numerous iframe problems with Ace: fixing it in CodeJar was much easier!

Get instance back from the dom element

Is there a way to get the jar instance from the dom element somewhere else?

// let's say this is a closure
(function() {
  const editor = document.querySelector('#editor');
  const jar1 = new CodeJar(editor, Prism.highlightElement, {tab: '\t'});
})();

Can we get the jar instance from somewhere else? Say another closure:

(function() {
  const editor = document.querySelector('#editor');
  // proposed way:
  const jar2 = CodeJar.from(editor);
  // jar2 === jar1
  jar2.updateCode('let foo = bar');
})();

withLineNumbers not working with Angular 12

I'm using codejar with prismjs in my Angular app, but when I try to use the module withLineNumbers, it does not work.

I created a test project in order to make it easier for you to reproduce: https://github.com/julianpoemp/angularCodeJarSample

I get the following error in the web console:

core.js:6456 ERROR TypeError: (0 , codejar_linenumbers__WEBPACK_IMPORTED_MODULE_3__.withLineNumbers) is not a function
    at AppComponent.ngAfterViewInit (app.component.ts:33)
    at callHook (core.js:2526)
    at callHooks (core.js:2495)
    at executeInitAndCheckHooks (core.js:2446)
    at refreshView (core.js:9512)
    at renderComponentOrTemplate (core.js:9555)
    at tickRootContext (core.js:10786)
    at detectChangesInRootView (core.js:10811)
    at RootViewRef.detectChanges (core.js:22858)
    at ApplicationRef.tick (core.js:29648)

on a previous Angular version (11), I got the error in the terminal:

Error: ./node_modules/codejar/linenumbers.ts
Module build failed (from ./node_modules/@ngtools/webpack/src/index.js):
Error: /Users/julian/repos/angularCodeJar/node_modules/codejar/linenumbers.ts is missing from the TypeScript compilation. Please make sure it is in your tsconfig via the 'files' or 'include' property.
The missing file seems to be part of a third party library. TS files in published libraries are often a sign of a badly packaged library. Please open an issue in the library repository to alert its author and ask them to package the library using the Angular Package Format (https://goo.gl/jB3GVv).
    at AngularCompilerPlugin.getCompiledFile (/Users/julian/repos/angularCodeJar/node_modules/@ngtools/webpack/src/angular_compiler_plugin.js:951:23)
    at /Users/julian/repos/angularCodeJar/node_modules/@ngtools/webpack/src/loader.js:43:31
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:94:5)

Here is my code:

import {CodeJar} from 'codejar';
import * as Prism from 'prismjs';
import 'prismjs/components/prism-json';
import { withLineNumbers } from 'codejar/linenumbers';

//...

const testJSON = {
        test: 'ok',
        something: 123456
      };
      const highlightMethod = (editor: HTMLElement) => {
        // Do something with code and set html.
        const textContent = (editor.textContent) ? editor.textContent : '';
        editor.innerHTML = Prism.highlight(textContent, Prism.languages.json, 'json');
        console.log(`highlight`);
      };
      this.codeJar = CodeJar(this.editor.nativeElement, withLineNumbers(highlightMethod), {tab: '\t'});
      this.codeJar.updateCode(JSON.stringify(testJSON, null, '\t'));

//...

How can I fix this? I really like codejar and I would like to use it in my app ๐Ÿ˜„

FireFox ctrl+a dont work (CodeJar 3.5.0)

Hey, we using Angular 12 with CodeJar 3.5.0 and have problems with FireFox and CTRL+A.

When you try to mark all text with CTRL+A and e.g. copy it with CTRL+C in FireFox it's don't working.

after CTRL+A the text is selected, but when you press CTRL again the text is deselected or somtimes only the last part.
When you use the mouse for select all the text or the shift+arrow keys and press CTRL works fine. Chrome has no problems with this. I have try it in CodeJar 3.4.0 with FireFox and there you also have no problems with CTRL+A, my current workaround is downgrade to CodeJar 3.4.0

I hope you can find and fix it, so we can stay up to date with the newest version of CodeJar :)

Bug with highlight.js highlight function

Hi !

There is a bug with the highlight.js highlight function

Here's what I see:

Screen Shot 2020-06-09 at 9 05 43 PM

Here's what I should see:

Screen Shot 2020-06-09 at 9 03 16 PM

It's only if I write the text, if I paste it, everything is fine

Just in case, here's how I initialized CodeJar:

CodeJar(editor, hljs.highlightBlock);

I also spotted this, not sure if this can help:

out

Instead of replacing the span on edit, it seems that a new one is inserted inside the first one

๐Ÿ› The Input cursor

The Input cursor is not staying on its place whenever i start typing.

Here is an easy mock:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Cody</title>
  </head>
  <body>

    <div class="editor language-js"></div>

    <script src="./node_modules/prismjs/prism.js"></script>
    <script type="module">
      import { CodeJar } from "https://medv.io/codejar/codejar.js";

      const editor = document.querySelector(".editor");

      const jar = CodeJar(editor, Prism.highlightElement);
    </script>
  </body>
</html>

Toolbar for markup languages?

It would be a boon for users of markdown and textile (even more because it does not depend on a specific syntax highlight) a toolbar for these languages. Or for one of them, but easily modified for others. The options currently available are often quite heavy and cannot be used with external syntax highlighting.

Code Execution Feature

Hi @antonmedv,

with Judge0 there could easily be an optional code execution feature with an integrated "Run" button that would allow anybody to run the code.

What do you think about it?

Best regards,
Herman

Overflow outside container

img

So I have a very long string, which makes it go outside the container. I have added a width: 100% on the editor and overflow:scroll, but it does not seem to work.

How would I go about this solving this issue?

Set language markup for PrismJS

Having this code:

let jar = new CodeJar(document.getElementById(this.name), PrismJS.highlightElement);

How does someone tell to this it needs to use the php language as highlight, or css for example?

I tried setting the language-php class to the div, but no dice.

Thanks!

Deleting last line

When I delete all characters in the last line, the cursor moves up to the previous line, which is different from the typical behavior of most editors. In all editors that I am used to, the cursor still stays in the last line without moving up. I wonder whether this behavior is intentional and whether there is any way to change it (or add an option to let it behave differently).

Jun-16-2020 09-32-42

Every keypress resets caret to bottom

Hi, I am trying to use this library but whenever I type and then move back in the document to edit, any keypress resets the cursor to the bottom of the document.

I am using the most basic example provided using HighlightJS.

I don't see anything that could be causing the cursor to jump to the bottom and don't see any settings in the demo that handles for this.

Any help would be most appreciated!

How to define language with PrismJS?

I installed both codejar & prismjs, but I fail to see how I can define the language here so syntax highlighting gets picked up:

<div class="editor"></div>
<script>
  let jar = new CodeJar(document.querySelector('.editor'), Prism.highlightElement)
</script>

Can you guide me in the right direction?

Configuring line numbers style?

Hi, I'm from lobste.rs! Trying out your library, and have few questions/suggestions regarding the line numbers.

At the moment line numbers style isn't configurabe (apart from the width). Couple of suggestions that would help with it:

  • do you think it makes sense to add a class element to the line numbers div (i.e. .codejar-linenumbers), that way it would be possible to retrieve it later and set/adjust the attributes dynamically?
  • alternatively, the init function could take in. Although I feel that it's hard to anticipate what people might want to tweak, so to prevent the Options type from bloating, maybe it's enough to let the users set the style via normal means

Another thing is: the default style is while color on the transparent background. It looks nice on the dark editor block, but mine was white and at first I thought the line numbers weren't working. Maybe it makes sense to make the line numbers block background non-transparent by default, so it contrasts and is visible regardless the underlying block?

Let me know what you think, also happy to contribute when I get a bit of free time!

ReadOnly mode possible?

Thanks for your great job.
I have a question/suggestion. Is there any feature of readonly? if not, it will be a great feature of this nice work.

And furthermore, it would be nicer if it is controllable by API on flight time. For example, jar.readonly(true) or something.

undo event not working on german keyboard layout

When using the german qwertz layout, pressing cltr + z does nothing because the z key is KeyY

Keyboard events are messy in javascript, the mozilla docs marks event.which, event.keyCode and event.charCode as deprecated and tells you to use event.key but as the PR #58 shows, event.key might be 'z' in german and english, no matter what layout but 'ั' in russian.

I don't know why they deprecate all numeric properties and give us no alternative and the keyboard.getLayoutMap api is still experimental.
But it should also be noted that big libraries like mousetrap also rely on event.keyCode and many many js projects use the classic if event.keyCode === 13 to check for enter, so its not sure if it will ever be deprecated since it would break a lot of code.

What do you think about using event.keyCode ?

I would suggest as a fix you could make the isUndo and isRedo functions somehow configurable, that way we could also configure it to be ctrl+z for undo and ctrl+y for redo instead of ctrl+z and ctrl+shift+z

Default style of the editor

Hi! Could you please give advice about how to change the default style of the editor? I saw an example in README how to assign a custom style, but CSS property "resize" on editor div always has value "vertical".

Scroll on new line

When I press return to make new lines to the point it overflows or out of viewport, the scroll doesn't follow the caret.

I think this is will be a pretty intuitive feature as it's common in most text editors. Sublime does it, and even this textarea I'm typing in does it.

New line issue in Firefox

In Firefox when I press on Enter the cursor stays on the current line, if I press a key then it appears on a new line but it's still very disturbing.

Everything is fine in Chrome though

Happens on the example page when I remove all the code of one of the editors and write some new

undo/redo wrong key shortcut

First let me tell you've done a great job! I love small & smart base codes.

how it works
undo: ctrl-y / redo: ctrl-shift-y

expected
undo: ctrl-z / redo: ctrl-y

I'm working on linux/windows with QWERTZ keyboard.

Selection doesn't preserve direction

If I start a selection going left, as soon as I release the key the selection gets "reversed" and successive arrow key presses start modifing the selection on its right edge.

Edit. You are using startContainer and endContainer to save the selection and setStart and setEnd to restore it. A possible solution would be to use Selection.anchorNode and Selection.focusNode on save and Selection.setBaseAndExtent on restore.

Getting current selection

I can see save() function in main file.
Sometimes, its output can be useful (as example for intellisense, peeking errors).
So, perhaps it can be enhanced with new features (like screen cursor coordinates), and added to exports?

Cursor Position is not restored correctly when pasting multiple lines

Hi

CodeJar does not restore the cursor position correctly when pasting multiple lines. I have encountered this on Windows computers and the Chrome browser. I also tested this on the latest CodeJar on the front page of the CodeJar website.

This is encountered because CodeJar counts \r as a character, but when Chrome pastes the text it gets rid of the \r leaving just \n. So the cursor position moves forward instead of correctly restoring.

Example:

// Start state
text = 'a'
cursorPos = 0 // cursor is at beginning of text
clipboard = 'b\r\n1'
  1. CodeJar inserts the clipboard
  2. The browser gets rid of \r and inserts the clipboard
  3. CodeJar restores the position using text.length which counts \r
// End state
text = 'b\n1a'
cursorPos = 4 // cursor is at end of text
clipboard = 'b\r\n1'

From this the cursor position is now 1 space ahead of where it should be.
This increases for each new line copy-pasted this way.

Potential Fix:
I have created a potential fix for this bug by changing the handlePaste function to:

function handlePaste(event: ClipboardEvent) {
  preventDefault(event)
  let text = ((event as any).originalEvent || event).clipboardData.getData('text/plain')
  text = text.replace(/\r/g, '') // This gets rid of any \r characters in the clipboard
  const pos = save()
  insert(text)
  highlight(editor)
  restore({ start: pos.start + text.length, end: pos.start + text.length })
}

Paste over selection

When a part of text is selected, paste replaces it but the caret moves by textToPaste.length (desired) + selection.length (undesired). When no text is selected, the behavior is as expected.

Update withLineNumber with new highlight method

Hello!
I am using the withLineNumber module and there's this case of changing the highlight method according to the language selected by user.

Now as there are no means to update the highlight method using the instance created by CodeJar, I create a new instance of CodeJar and pass the new highlight method. When I do this, the withLineNumber function is adding new wrapper div on top of editor because of the init method being called every-time the language changes.

I was wondering if there was check like this in the withLineNumbers then it would just bypass the init process as it has already been initialised

let lineNumbers = document.querySelector(` .${opts.class}`)

https://codesandbox.io/s/blissful-chaplygin-e794q?file=/src/App.js

or is there a better way to do this?

cpp highlight not work

Hi, I have used this in my react-app together with highlight.js.
There are several issues I have encountered:

  • cpp highlight not work with highlight.js, my code:
    import cpp from  'highlight.js/lib/languages/cpp';
    hljs.registerLanguage('cpp',cpp);
  • themes switch
    I use the method that once user clicks a new theme, corresponding theme's .css file will be loaded, e.g.
     require('highlight.js/styles/'+this.state.theme+".css");
    but in that mode, if I use theme a, then switch to theme b, then switch to theme a, theme won't be changed

Jar sets editor resize style to 'vertical' by default

Jar sets editor resize style to 'vertical' by default. What is the purpose behind this behavior?
Ideally it should be optional. I am having to do the following:

        let editor = document.querySelector('#query-editor')
        const highlight = (editor) => {
            const code = editor.textContent
            // Do something with code and set html.
            editor.innerHTML = code
        }

        this.jar = CodeJar(editor, highlight)
        editor.style.resize = 'none';

Feature request: server-side rendering

It would be perfect if codejar provided a react component which would work in both server and browser environments.

The second best option is a function like render(text) which would work on the server and return an HTML, identical on both sides. So re-rendering this HTML on the client would not cause page jump/blink. This function could be used to implement react component.

The third best option is a function like render(text) which would work on the server, and return HTML without syntax highlighting, so that re-rendering the same component in the browser only caused highlighting change, but no size/position changes.

Why it is important:

  • server-side rendered pages are friendlier to search engines, slow internets and slow computers and people who disable JS
  • when a page is only partially rendered on the server (with everything rendered on the server, but text editor rendered on the client), the page jumps/blinks on load, which is suboptimal from UX point of view

Failed to execute 'getRangeAt' on 'Selection': 0 is not a valid index.

Hi,
I'm getting the following exception in Chrome as soon as I'm typing a character:

Uncaught DOMException: Failed to execute 'getRangeAt' on 'Selection': 0 is not a valid index.
    at afterCursor (https://medv.io/codejar/codejar.js:180:22)
    at handleSelfClosingCharacters (https://medv.io/codejar/codejar.js:234:27)
    at HTMLDivElement.<anonymous> (https://medv.io/codejar/codejar.js:55:13)

My setup is rather unique (e.g. dynamical import of the module), so expect it's a problem with my setup. I tried both highlight.js and Prism, both same result. Any pointers to where the problem lies would be much appreciated.

Thanks,
Thomas

Missing options

Hey ! Thanks for your awesome lib !

Can you update the package on npm to match the latest documentation ?
The option "addClosing" is missing from the published package (and there is a small typo "identOn" => "indentOn").
Thanks !

Cursor position wrong after (1) CTRL+A and (2) `"` character is entered

Hi @antonmedv

First of all, thanks for your work on codejar! ๐Ÿ™‚

I noticed the following issue with the cursor position: When the editor content is selected with CTRL+A and after the " character is entered, the cursor is placed at behind the two "" characters instead of the middle. This seems to happen no matter what the input is, except when it is already "" before - then the cursor is placed before the two "" characters.

When I select the entire content of the file using my mouse or SHIFT + arrow keys, the issue doesn't appear: The cursor is placed correctly between the two "" caracters.

I was able to reproduce the issue in both Firefox and Chromium.

The web page does not respond when deleting more than 400 lines of code using Ctrl+A

Node: v14.15.1
OS: Windows 10

About 400 lines of Javascript code, select and delete all, and the whole page will be unresponsive for about 5 seconds.

Code:

import { CodeJar } from "codejar";
import { withLineNumbers } from "codejar/linenumbers";

import { highlight, languages } from "prismjs/components/prism-core";
import "prismjs/components/prism-clike";
import "prismjs/components/prism-javascript";
import "prismjs/themes/prism-tomorrow.css";

const editor = document.querySelector("#file-code-editor");
const highlightFunc = (editor) => {
    const code = editor.textContent;
    editor.innerHTML = highlight(code, languages.js);
 };
this.editor = CodeJar(editor, withLineNumbers(highlightFunc), {
    history: false,
    spellcheck: false,
    catchTab: false,
    preserveIdent: false,
    addClosing: false
});

Changing the highlightFunc function to this will solve this problem, but you will lose the text color.

  const highlightFunc = (editor) => {
      const code = editor.textContent;
      editor.innerHTML = code;
      // editor.innerHTML = highlight(code, languages.js);
    };

Is there any better way to solve this problem?

Firefox enter before certain characters doesn't move cursor to the new line

Screen.Recording.2021-04-23.at.13.29.32.mov

When typing the first line and I press "Enter" the cursor and the final ' follow me down to the next line.

In my second example when pressing "Enter" before the ?, a new line is created however the cursor doesn't follow me in this scenario.

I have tested in Chrome and Safari and all works well on those browsers so I am guessing it has something to do with the firefoxNewLineFix function that intercepts the "Enter" key and adds a new line.

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.