GithubHelp home page GithubHelp logo

qlik-oss / nebula.js Goto Github PK

View Code? Open in Web Editor NEW
77.0 20.0 56.0 29.51 MB

Product and framework agnostic integration APIs for Qlik's Associative Engine

Home Page: https://qlik.dev/extend/set-up-nebula-environment/

License: MIT License

JavaScript 99.51% HTML 0.40% CSS 0.02% Shell 0.06%
qlik sense engine qix extension mashup

nebula.js's Introduction

nebula.js logo

A new star on the rise

NebulaJS is a collection of JavaScript libraries, charts and CLIs that helps developers build and integrate visualizations on top of Qlik's Associative Engine. The collection is organized under the @nebula.js npm scope.

The primary package is @nebula.js/stardust which contains APIs for integrating existing visualizations into mashups, as well as APIs for building custom visualizations.

Documentation

You can find the documentation on Qlik's developer portal.

To quickly get started, check out the tutorial on how to embed visualization into your own web app.

You can also walk through the tutorial on how to build your own extension.

Explore the full stardust API reference.

Contributing

Follow the instructions in our contributing guide.

Core modules

name status description
stardust stardust-status Core nebula.js module

License

nebula.js/stardust is MIT licensed.

nebula.js's People

Contributors

a-m-dev avatar aihazm avatar ashrles avatar caele avatar cbt1 avatar chinmay-sg avatar daniels-qlik avatar dependabot[bot] avatar devisscher avatar donya-qlik avatar eliseeborn avatar fredrikfolkeryd avatar haxxmaxx avatar johanlahti avatar likang6688 avatar linhnguyen-qlik avatar miralemd avatar niekvanstaveren avatar nilzona avatar pernyl avatar purwashrivastava avatar quanho avatar renovate[bot] avatar stefanenberg avatar stoffeastrom avatar streamside avatar t-wizard avatar tassekatt avatar vcellu avatar veinfors 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

Watchers

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

nebula.js's Issues

Cell composition

Update cell composition with correct spacing between subcomponents:

Cell compositions

Responsive current app selections

๐Ÿš€ Feature

Responsive current app selections.

Motivation

The current app selections toolbar needs to be responsive and support any number of selected fields.

Additional context

Design

Responsive selections

Example projects

๐Ÿš€ Feature

Example projects to get started making more advanced and production like extensions.

  • Preact boilerplate
  • End to end testing with interactions
  • Mashup
  • Container Extension
    • An extension that load and show another nebula inside the extension element with nucleus
  • Angular 7 boilerplate

Motivation

Off load the documentation burden with example project for developer to test and see best practices.

UI overlay on failure

Build failures in a supernova would be more visible if a UI overlay is shown when something goes wrong (similar to the one used by webpack-dev-server). The only other option is keeping an eye on the console, which is usually kept in the background.

Screen Shot 2019-05-13 at 09 24 30

Custom actions UI

๐Ÿš€ Feature

UI for custom actions.

Motivation

Visualizations might have custom actions to perform things like:

  • Export data
  • Export as image
  • Reset something (scroll, sorting etc)
  • Search
  • Custom selection behaviour (like lasso)
  • Go full screen

Providing developers with an embedded UI where these actions are located creates a more cohesive look and feel.

Since the useAction hook in supernova is run on every frame and can therefore be updated, developers can provide contextual actions depending on current data and interactions performed by a user.

object-actions

This might remove the need for a context menu #41

nucleus.createConfiguration is not a function

๐Ÿ› Bug report

Given attached sample code, nucleus.createConfiguration throws an error saying it's not a function

Steps to Reproduce

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>Nucleus test</title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="">
    </head>

    <body>
        <!--[if lt IE 7]>
            <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->
        <div style="height:500px;" id="chart"><p>Hello World!</p></div>
        
    </body>
    <script src="https://cdn.jsdelivr.net/npm/enigma.js" crossorigin></script>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js" crossorigin></script>

    <script>
        const urlQlikServer = "https://jog.us.qlikcloud.com";
            const urlLoggedIn = "/api/v1/users/me";
            const urlLogin = "/login"
            const webIntegrationId = 'CJjKP_nzi9sy72SMEniHwhawFra0jgOT';

        async function connect() {
            

            //Step 1: Check to see if logged in
            return await fetch(`${urlQlikServer}${urlLoggedIn}`, {
                credentials: 'include',
                headers: {                  
                    'Qlik-Web-Integration-ID':webIntegrationId
                }

            })
            .then(async function(response)
            {
                if(response.status===401){
                    const url = new URL(`${urlQlikServer}/login`);
                    url.searchParams.append('returnto', 'http://localhost:3001/mashup');
                    url.searchParams.append('qlik-web-integration-id', webIntegrationId);
                    window.location.href = url;
                }

                return await fetch(`${urlQlikServer}/api/v1/csrf-token?qlik-web-integration-id=${webIntegrationId}`,
                {
                    credentials: 'include',
                    headers: {                  
                        'Qlik-Web-Integration-ID':webIntegrationId
                    }
                })
                .then(function(response)
                {
                    console.log(response.headers.get('qlik-csrf-token'));
                        return response.headers.get('qlik-csrf-token');
                })
                .then(function(headers)
                {
                    console.log(headers)
                    return headers;
                });
                

            })
            .catch(function(error)
            {
                if(error.response.status===401)
                {
                    const url = new URL(`${urlQlikServer}/login`);
                    url.searchParams.append('returnto', 'http://localhost:3001/mashup');
                    url.searchParams.append('qlik-web-integration-id', webIntegrationId);
                    window.location.href = url;
                }
            });
            
    }

    connect()
    .then(async function(token)
    {
        const schema = await (await fetch('https://cdn.jsdelivr.net/npm/[email protected]/schemas/12.170.2.json')).json();

        const enigmaGlobal = await enigma
            .create({
            schema,
            url: `wss://jog.us.qlikcloud.com/app/486e1036-17a3-46b9-a552-b664c4f7afd8?qlik-csrf-token=${token}&qlik-web-integration-id=${webIntegrationId}`,
            //createSocket: url => new WebSocket(url)
            
        })
            .open();

        const enigmaApp = await enigmaGlobal.openDoc('486e1036-17a3-46b9-a552-b664c4f7afd8');
        
        const n = nucleus.createConfiguration({
        types: [
            {
            type: 'barchart',
            load: () => Promise.resolve(window['@nebula.js/sn-bar-chart']),
            },
        ],
        });
        n(enigmaApp).render({
            element: document.querySelector('#chart'),
            id: 'qZPdytp',
        });       
    })
            

        

    </script>
   
   
    <script src="https://cdn.jsdelivr.net/npm/@nebula.js/supernova" crossorigin></script>
    <script src="https://cdn.jsdelivr.net/npm/@nebula.js/nucleus" crossorigin></script>
    <script src="https://cdn.jsdelivr.net/npm/@nebula.js/sn-bar-chart" crossorigin></script>

        


</html>

Expected behavior

I expect a chart to render

Actual behavior

a chart doesn't render

Versions

  • nebula.js: latest
  • Platform: QCS public
  • Browser: Chrome

(Add any other context, link to demo or screenshots about the issue.)

Assets

Add an assets view for faster access to fields, measures, dimensions etc.

Theming

Motivation

White labeling and customizing the look and feel is an important aspect of integration for mashups.

Concerns

  • Modifying styles by directly referencing CSS classes isn't ideal as various integrations could easily interfere with eachother.
  • Supporting different versions of nebula (which could have different styles in different versions) in the same page would also be a risk of clashing styles.
  • Applying a different style per chart on the same page should also be possible.
  • UI and visualizations should be broken down into components, the theme is defined on component level, not on chart level.

Solution

For those reasons we will be taking a CSS-in-JS approach as it will minimize the above risks.

The definition of a theme might look like this:

{
  typography: {
    fontFamily: '"Source Sans Pro", Arial, sans-serif',
    fontSize: '14px',
  },
  palette: {
    primary: 'green',
    secondary: 'purple',
    background: '#fafafa',
    surface: '#ffffff',
    text: {
      primary: '#404040',
      secondary: '#999',
    }
  },
  shape: {
    borderRadius: 4
  },
  data: {
    nil: '#eee',
    categorical: ['red', 'green', 'blue'],
  },
}

Themes are used per app and nucleus instance:

const nebbie = nebula(enigmaApp).theme({ typeography: { fontFamily: 'Georgia' }});

// all charts created from the same nucleus instance will have the same theme
nebbie.get({ id: 'fgdtr' }, { element });
nebbie.get({ id: 'fs4fr' }, { element });

// it should be possible to apply a different theme to a different instance on the same page
const nebbie2 = nebula(enigmaApp).theme({ typeography: { fontFamily: 'Monaco' }});
nebbie.get2({ id: 'adfs3' }, { element });
nebbie.get({ id: 'bcnhj' }, { element });

Hooks

The hooks concept introduced by React could be very fitting to use since a component in supernova is very similar in terms of lifecycle. Custom hooks could easily be shared for reusability and increased productivity.

Example hooks:

  • useState to handle state (same as React)
  • useLayout to consume a layout
  • useModel to access the current object's enigma model
  • useApp to access the app model
  • useTheme to consume a theme
  • useResize to handle a resize
import { useLayout, useResize } from '@nebula.js/supernova'

export default function() {
  {
    qae: { /* */ },
    component() {
      const [state, setState] = useState({});
      const [layout] = useLayout();
      useResize(() => { /* do stuff on resize */ });

      // render stuff
    }
  }
}

Export image

Add support for image export in order to enable testing/debugging the snapshot capability.

Related to #26, #29

Better "Incomplete Visualization" message

๐Ÿš€ Feature

Based on the hypercube requirements coming from the supernova we're rendering the messages should be showing what is missing until requirements are met.

Motivation

Much better user experience

Additional context

If for some reason there are technical limitations blocking this feature it would be nice to be able to control the rendering of the "Incomplete Visualisation" from the api.

Type definitions

Typescript definitions would not only help those who use TypeScript, but also those who use tools that take advantage of typing definitions to provide intellisense.

Should be generated automatically through scriptappy and JSDdoc within the code.

NPM install throwing gyp erros

๐Ÿ› Bug report

When running npm install @nebula.js/cli@next -g receives this error in terminal
image

Steps to Reproduce

  1. Open terminal in Mac
  2. run npm install @nebula.js/cli@next -g

Expected behavior

clean install

Actual behavior

see screenshot:
image

Versions

  • nebula.js: 0.2.0-alpha.1
  • Platform: Mac
  • Browser: ?

Additional context

None.

TypeError: boo.selections(...).mount is not a function

๐Ÿ› Bug report

Using code sample on this page: /docs/app-selections

  1. Missing closing parens on the line await (n.selections()).mount(document.querySelector('.curr-selections');

  2. When adding this function to mashup, error TypeError: boo.selections(...).mount is not a function appears
    code: ```
    const n = nucleus.createConfiguration({
    types: [
    {
    name: 'barchart',
    load: () => Promise.resolve(window['@nebula.js/sn-bar-chart']),
    },
    ],
    });

     n(enigmaApp).render({
         element: document.querySelector('#chart'),
         id: 'qZPdytp',
     }); 
     
     const boo = nucleus(enigmaApp);
     await (boo.selections().mount(document.querySelector('.curr-selections')));    
    

### Steps to Reproduce

Try the code that is in the documentation.

### Expected behavior

Code in documentation works

### Actual behavior

Code samples in documentation aren't working

### Versions

- nebula.js: 0.2.0
- Platform: 
- Browser: Chrome


`ACCEPT_EULA=yes npm start` does not work on Windows

๐Ÿ› Bug report

Running a command that starts with an environment variable does not work on Windows.
Implementing https://www.npmjs.com/package/cross-env is a possible solution for this problem.

Steps to Reproduce

  1. Run ACCEPT_EULA=yes npm start in the cmd on Windows
    image
    or
  2. Add ACCEPT_EULA to the environment variables on Windows
  3. Run nebula serve
    image

Expected behavior

That the nebula project is served at localhost:8080
image

Versions

  • nebula.js: (0.1.0-alpha.13)
  • Platform: Windows
  • Browser: Chrome

Additional context

This needs to be updated
https://github.com/qlik-oss/nebula.js/blob/master/packages/serve/lib/engine.js#L11
And the readme at row 113

Nebula Qlik Sense

๐Ÿ› Bug report

I'm trying to export a nebula visualization into Qlik Sense using cmd command sense, but when I copy the files into extensions directory of Qlik Sense Desktop and then run the extension, the extension doesn't show anything.

Steps to Reproduce

  1. cmd command --> sense in my nebula visualization
  2. copy the .js, .qext and dist files into extensions directory
  3. run the extension in Qlik Sense Desktop

Expected behavior

Plot de visualization correctly

Actual behavior

The extension doesn't show the data.

Versions

  • nebula.js: (0.6.0)
  • Platform: Qlik
  • Browser: Chrome

Additional context

This is a simple hypercube visualization in nebula.

Captura de pantalla (46)

And when I try to export into Qlik Sense

Captura de pantalla (49)

Versioning

A Qlik Sense extension today is comprised of primarily two parts:

  • object properties, which are stored in an app
  • rendering logic (extension), which is uploaded to a Qlik Sense installation

Since both of them change over time but are stored differently, it's very easy to end up in a situation where the two are not compatible.

Example:

  1. You add a new property in initialProperties of an object
  2. You update the code in your extension to depend on the new property and upload the extension

All newly created objects will have the new property and everything will work fine. However, if you open an app containing an object that was created before you made the property changes, your extension might crash if the old properties are not taken into account. This becomes a bigger problem over time as changes are made in both the rendering logic and properties.

This problem could be solved by implementing versioning of both the object properties and rendering logic.

provide custom themes

๐Ÿš€ Feature

Make it possible to apply custom themes:

const n = nucleus(app, {
  themes: [{ key: 'darkish', load:() => Promise.resolve({ type: 'dark', color: 'red'})}]
});

n.theme('darkish');

Visualisation packages for a specific Sense release

๐Ÿš€ Feature

Visualisation packages for a specific Sense release

Motivation

To shorten the time to get started building web solutions that embeds Qlik visualisations it would be nice to be able to npm install a bundle of visualisations.

npm install @qlik/sense-april-2020 or npm install @qlik/sense:latest

new style element added on every hot reload

๐Ÿ› Bug report

Bundles including CSS will inject <style> on hot reload

Steps to Reproduce

  1. nebula serve from root of repo
  2. import foo.css in index.js containing any style
  3. change something in the CSS - both the old and new styles are applied

Expected behavior

Current CSS should be the only applied style

Actual behavior

A new <syle> element is added every time the supernova is hot-reloaded

Versions

  • nebula.js: 0.1.0-alpha.30
  • Platform: All
  • Browser: All

Additional context

Issue caused by the bundler which injects the style element as soon as the bundle is parsed and executed, nebula itself has no control over it.

Consume theme

Provide an API for consumption of a theme.

component: {
  created({
    theme
  }) {
    this.theme = theme;
    theme.on('changed', () => { /* handle change */ });

    const def = theme.definition();
    console.log(def.data.categorical);

    def.classes('Button'); // get the CSS classes for a <button>
  }
}

Related to #24

Consume translator

Provide an API for the consumption of localized strings:

component: {
  created({
    translator
  }) {
    translator.get('Back');
  }
}

Related to #25

Adapt Sense theme to nebula

The current plan for theming in nebula is quite different from how theming is done in Sense. The Sense theme definition needs to be mapped to a nebula theme in order to provide the same API for a supernova regardless of whether it's being used in Sense or outside.

Related to #27

Does not render in Safari

๐Ÿ› Bug report

When running the sample template and editing the Picasso specification, rendering is not updating properly to the size of the window in Safari browser. The same code works fine in Chrome.

Also the code settings and previews don't work and produce blank screens in the browser.

Steps to Reproduce

  1. Create Nebula project
  2. Open in Safari
  3. Open Settings (get blank screen)
  4. Edit hypercube and main chart area does not update to the correct result. The screen does not update when browser is changed in size.

Expected behavior

The chart should be shown and displayed the same as it does in Chrome.

Actual behavior

Incorrect chart rendering or blank screen.

Versions

  • nebula.js: 0.2.0-alpha.1
  • "@nebula.js/supernova": "^0.1.0-alpha.28"
  • Platform: Mac OS
  • Browser: Safari

Additional context

(Add any other context, link to demo or screenshots about the issue.)

Snapshots

Snapshots play a key role in exporting images and storytelling.

When a component is exported, a snapshot is taken of the current layout and is then rendered in the backend using that layout. This works fairly well as long as the enigma model is not used to e.g. fetch more data.

The developer should therefore be allowed to control what is included in the snapshot in order to reproduce the state of the component without the presence of a backend.

component: {
  render({ layout, context }) {
    if (layout.additionalData) { // assume a snapshot is being rendered
      // render stuff
    } else if (context.permissions.indexOf('fetch') !== -1) { // access to engine is permitted
      this.model.getHyperCubeData(/* */).then((pages) => {
        this.additionalData = pages; // temporarily store the data
      });
    }
  },
  takeSnapshot({ layout }) {
    // store the additional data
    layout.additionalData = this.additionalData;
  }
}

Related to #26

Generate property panel from properties

It's possible today to modify the properties of an object by using the properties dialog. It would however be faster if it was possible to do from a property panel similar to the one in Sense.

Since the panel definition here won't matter anywhere else, the best option would be to generate a property panel based on the property names and types.

Export image

Motivation

Exporting images is important for reporting.

Solution

A minimal nodejs service that:

  • would receive a snapshot from the client
  • render the snapshot using headless Chrome

Concerns

Using headless Chrome requires Chrome to be installed on the machine running the service.

The mashup developer would be responsible for running the service.

Handle field requirements

Charts that have requirements on a specific amount of dimensions and measures should not be rendered unless those requirements are met. qError on dimensions and potentially also measures should be taken into account when validating.

An overlay should be rendered when the requirement is not fulfilled.

As it appears in Sense:
Screenshot 2019-11-05 at 10 12 56

Experimental feature toggle

๐Ÿš€ Feature

A way to toggle experimental features.

Motivation

It's common in continuously delivered products to toggle features on the fly, whether it's for A/B testing or for a phased rollout of a new feature.

Documentation

  • Getting started
    • Installation
      • npm, yarn, CDN
    • What is nebula.js?
    • Usage
      • Connecting to engine
      • Rendering a chart
  • Nucleus guide
    • Configuration
      • theme, language
      • constraints
      • types
        • loading charts on the fly with d3-require
      • themes
      • snapshots
    • rendering charts
      • element requirements - size position
      • by type
        • initial fields
      • by id
    • app selections
    • supernova controller
      • set properties
      • export image
      • set options
  • Supernova guide
    • Prerequisites
    • instant prototyping
    • Hello world
    • Component + QAE
    • Add stuff to element
    • Consume data
    • Basic hooks
    • actions
    • Use theme
    • use translator
    • Use model, app, global
    • Snapshots
    • Options + imperative handle
    • Build + publish
      • loaders
      • peer deps
  • CLI
    • install
    • serve
    • build
    • create
  • Guides
    • API design approach
    • Testing
  • API reference
    • nucleus
    • supernova
    • snapshooter
    • CLI
      • create
      • build
      • serve
      • nebula config
  • FAQ
    • Versioning policy, API governance and release tracks
    • Browser support

Context menu

Provide a context menu API to allow developers to add their own actions to existing context menus.

Responsive object selections

๐Ÿš€ Feature

Responsive object selection actions.

  • Inline in header when title is visible
  • In popover when title is not visible, or when object is too small to fit the actions inline

object-selections

Export data

Motivation

Exporting data is a crucial feature for mashup developers.

Approach

  • exportData might be enough on QSEoW
  • REST call for QCS?

Handle errors in generic object

Generic objects containing hypercubes, listobjects etc can have bad expressions or other type of errors on the layout. These errors should be handled by rendering an error overlay and prevent the chart from rendering.

Types of errors:

  • Loading error: Loading of a type/chart/file failed
  • Internal error: Something internal
  • Chart rendering error:
    • qError on a hypercube/listobject
    • Error thrown when rendering chart

Extension definitions

๐Ÿ› Bug report

When using the nebula sense --ext command, can't create a external dependency.

Steps to Reproduce

  1. Create a project
  2. Create a extDefinition.js file where define extension definition
  3. Use sense --ext command

Expected behavior

Creates visualization-ext file with the extension definition for Qlik Sense.

Actual behavior

Inkedissue_LI

Versions

  • nebula.js: 1.0.0
  • Platform: Windows

Localization

Motivation

Localization is an important aspect of integration for mashups.

Concerns

String translations in Capabilities APIs and Extensions in Qlik Sense are provided by Qlik, who has teams of translators per language. Those translations need to be provided to nebula without the need for Qlik Sense.

Solution

There is a very limited set of strings needed for the UI in nebula, the best option might be to crowdsource those translations.

Support ListObject

๐Ÿš€ Feature

Add support for ListObjectDef as a data target:

qae: {
  properties: {
    foo: {
      qListObjectDef: {},
    },
  },
  data: {
    targets: [
      {
        path: '/foo/qListObjectDef',
      },
    ],
  },
},

More templates

Increase productivity and time to initial render by adding more project templates:

  • d3
  • more picasso charts
  • basic mashup example

Also consider more options in terms of project structure and workflow:

  • add stubs for unit, component and integration tests
  • eslint config, prettier

Chart bundler

nebula.js/nucleus is an API with the purpose to render charts (supernovae), however no charts are bundled with nebula to avoid large bundles and allow developers to choose which charts they need.

Since each chart is standalone and requires no dependencies, it usually means each chart will be quite large since libraries like picasso, react-dom, material-ui are bundled for each chart. To reduce the total size when using multiple charts, it would be beneficial to have some kind of tool that allows a developer to select with charts they intend to use, and to create one bundle where the shared resources/libraries are only bundled once.

cli example:

nebula bundle --charts bar line scatter

Support more loaders

The current rollup build config only supports JavaScript and CSS files, and will most likely need to be expanded.

This would however depend entirely on the need the community has; do we need to add support for LESS/SASS, images, text etc?

Theme editor

The current solution of theming using Material UI and CSS-in-JS allows us to change a theme at runtime. It would therefore make a lot of sense to include a theme editor as the results could easily be seen live as changes are made to the theme.

Related to #24

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.