Git Product home page Git Product logo

extensions-api's Introduction

Tableau Extensions API

Tableau Supported

Image of Flex the T-Rex

Why the Tableau Extensions API?

The Extensions API lets you do more without leaving Tableau. Build Tableau extensions that can interact and communicate with Tableau, and embed them directly in your workbooks.

Setup and Running Samples

Prerequisites

Install Extensions API SDK Components and Start Server

  1. Open a command prompt window to the location where you cloned this repo.

  2. Install the Extensions API SDK components.

    npm install

  3. Build the TypeScript samples and install the Extensions API types library.

    npm run build

  4. Start the local Dashboard Extension server.

    npm start

  5. Launch Tableau and try the sample extensions in a dashboard. The samples are located in the Samples folder.

Note The local web server you start just serves to host the extension samples and extensions used in the tutorial, which have URLs similar to the following: http://localhost:8765/Samples/DataSources/datasources.html or http://localhost:8765/Samples-Typescript/DataSources/datasources.html This local web server is not intended to serve the Extensions API Help pages. View the Help on GitHub at https://tableau.github.io/extensions-api.

Typescript Development

Samples written in Typescript are located in the Samples-Typescript folder. If you want to use TypeScript to write your extensions, you can run a script that starts up the HTTP server and actively listens for changes to the .ts files located in the Samples-Typescript folder. You can then add your extension to the folder and use the script to transpile your extension to JavaScript.

  • To start the the HTTP server and listen for changes to the .ts files.

    npm run dev

For more information, see Use TypeScript with the Extensions API.

Sandboxed Extension Development Environment

Tableau is introducing development support for Sandboxed Extensions with Tableau 2019.3. Sandboxed Extensions run in a virtual sandbox and ensure the extension can’t make network calls outside of the hosting Tableau Server. The Extensions API SDK provides a local development environment that replicates the Tableau Hosting Cloud Service for Sandboxed Extensions. You can test your Sandboxed extensions locally with the same sandbox policies.

  1. Start the local Sandboxed Extension web server.

    npm run start-sandbox

  2. Launch Tableau (Tableau 2019.3 and later) and try the sample Sandboxed Extension in a dashboard. You can find the .trex file and sample code in the Samples\UINamespace-sandboxed folder.

For more information, see Create and Test Sandboxed Extensions.

Contributions

Contributions and improvements by the community are welcomed! See the LICENSE file for current open-source licensing and use information.

Before we can accept pull requests from contributors, we require a signed Contributor License Agreement (CLA). To submit a contribution, please fork the repository then submit a pull request to the main branch.

Code Style

Our sample code follows the Semi-Standard Style for JavaScript samples linting and tslint for TypeScript. If you add your own extension code to the Samples or Samples-Typescript directories, you can run npm run lint to validate the style of your code. Please run this command before submitting any pull requests for Sample code.

npx semistandard --fix to fix linting issues which can be fixed automatically.

Documentation

Visit the project website and read the documentation here.

Issues

Use Issues to log any problems or bugs you encounter in the docs or sample code, or to discuss any proposed changes or additions.

extensions-api's People

Contributors

akovtunov avatar alicemhsiao avatar ankitpatel29 avatar ashwinar avatar b-carver avatar bcantoni avatar benlower avatar brtal avatar craigfis avatar d45 avatar deocastephen avatar dependabot[bot] avatar edmaust avatar elbandito avatar garudolph avatar illonage avatar jacalata avatar jdomingu avatar johndance avatar jz-huang avatar keshiarose avatar kovner avatar lbrendanl avatar mwhagedorn avatar nikhillakshman avatar sdesmond46 avatar seanmakesgames avatar stephendeoca avatar testbrendan avatar vishwasnavadak 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

extensions-api's Issues

Query underlying data size (column data and number of rows)

Hey, I'd like to be able to query the number of rows in the underlying data table, currently the DataTable returned by getUnderlyingDataAsync contains a totalRowCount but that is limited by the number of rows actually returned. I dont care about the actual individual rows in the data and therefore set maxRows to 1 but i get a totalRowCount of 1 instead of the actual size of the underlying data.

Aditionally if maxRows is not set Datasource.getUnderlyingDataAsync will return a totalRowCount of 10.000 instead of returning the actual row count of the underlying data.

Perhaps the upcomming pagination feature will allow me to set pageSize of 1 and report the correct totalRowCount but this is currently unclear as the feature is not yet implemented.

Refresh Data

Hi All,

Is there a way to capture/detect data changes on the dashboard in the add-in?

Thanks!

getFiltersAsync returns Invalid Date for cleared/empty date range filter

This is less a bug and more an inconvenience that I think is probably relatively simple to fix...

In the case of a date range filter DataValue.value seems to be the result of new Date(formattedValue), however in the case of an empty/cleared filter DataValue.formattedValue is "Null" and so the value ends up becomming an Invalid Date object.

There is no good way to handle invalid dates in JavaScript. For example it might look a bit like this:

let isInvalidDate = (date) => date instanceof Date && Number.isNaN(date.getTime());

Especially if you want to stuff this value back into the applyRangeFilterAsync method this becomes quite awkward as you will need to check for Invalid Date using this arcane thing above...

It'd be great if getFiltersAsync would just return null in DataValue.value instead if the filter is cleared/empty.

Proposal: Expose export crosstab api

currently this feature is only available on tableau server. But if user wants to download crosstab from multiple worksheets, will have to go through a modal dialogue for each worksheet.

cookies are not shared between extension and dialog

I would expect the extension and the dialogs that it is displaying to share the same cookies (cookiejar?), but it appears that this is not the case. Is this correct?
This makes authorizing and tracking users of extensions very difficult.

Event Type for Actions

As Tableau Actions are used a lot in Tableau they are handy to identify with the extension.

Right now the TableauEventType has a member 'filter-changed'.
It is possible to identify a dashboard action using some string comparison on 'action ('.

However this is ugly code and we would love to have a action-changed event to identify Tableau Actions

Unable to listen for KeyDown event on "T" key

While editing a dashboard on desktop, the "T" key seems to be overridden to toggle between Dashboard and Layout menus. Within my extension, I have a text input that currently ignores the "T" key; it'd be great if this hotkey was disabled while the user is interacting with an Extension.

Is this a known issue? Thanks.

Extensions are not getting recognised in Tableau Desktop 10.5.0 Beta macOS

Hi,
I have installed Tableau Desktop 10.5.0 Beta 2 on macOS. I have copied sample Datasource extension to extension folder. It's not showing up in the UI. I see below errors in log

{"ts":"2017-12-21T15:17:34.525","pid":48834,"tid":"b9cbb5","sev":"error","req":"-","sess":"-","site":"{50E95D04-58BD-4A68-9790-54C401A2DCFB}","user":"-","k":"msg","v":"AddIn Registration in File 'DataSources.trex': 'Error(2,89): no declaration found for element 'manifest' (id: /Users/madhu/Documents/My Tableau Repository (Beta)/Extensions/DataSources.trex)'"}

Followed your steps to install tableau extensions...

Followed your steps to install tableau extensions.But I am not able to see the extensions option in tableau server.

Steps Followed:
1.Download extensions-api-master zip folder from github. Install Node.js and npm
2.Copy the Parameters .trex files of the sample you wish to run to ~\Documents\My Tableau Repository (Beta)\Extensions so they are available to Tableau.
3.Open a command prompt window to the location where you cloned this repo.
4.Run npm install.
5.Run npm start

I am using Tableau desktop Professional Version 2018.1.0.
Please help me resolve the issue ASAP as I am new to using extension API.

Proposal: HTTPS Requirement

  • We will require https
  • Localhost exception (for Development purposes)
  • No redirects allowed
    • But you can change the url after the anchor tag (#) or can change query parameters
  • The API will allow a UI (dialog) for doing things like oAuth

[bug] error opening a dashboard containing an extension using the configure context menu item option

When saving and then opening a dashboard containing an extesion that has the configure context menu item i encounter an error:

Unable to complete action
Errors occurred while trying to load the workbook "C:\Users\tjalling\Downloads\test\test.twb". The load was not able to complete successfully.
Error Code: 
Errors occurred while trying to load the workbook "C:\Users\tjalling\Downloads\test\test.twb". The load was not able to complete successfully.
Error(58115,81): value 'configure' has length '9' which exceeds maxLength facet value '0' (id: C:\Users\tjalling\Downloads\test\test.twb)

The configure value the error seems to be referring to in the .twb looks like this:
(This is inside the <referenced-extension> tag)

<context-menu>
  <configure-context-menu-item>configure</configure-context-menu-item>
</context-menu>

This same value in my .trex file looks like this:

<context-menu>
  <configure-context-menu-item />
</context-menu>

When saving the workbook it seems its "unfolding" this element and giving it the content configure but when reading it expects the element to be empty.

When i manually change the .twb context menu element to <configure-context-menu-item /> the workbook opens fine but the extension seems to have lost its permissions as it will not show anything (not even the "Eextension was denied the required permissions" warning) until i select Reset Permissions from the context menu.

Addins folder

Hi All,

Is it possible to get the location of the Addins folder out of the registry?

I noticed you have a HKEY_CURRENT_USER\Software\Tableau\Tableau cpp\Directories entry, and I would like to be able to programmatically figure out where the Addins folder is located.

Thanks!

Dashboard action name

Would it be possible to retrieve the dashboard action name?
image

It would be helpfull with actions which are using the same dimension as they will have the same name right now. For example:
image

Scrolling awkwardness on OS X with Tutorial extension

When trying to display many selected marks in the sample Tutorial Complete extension, the scroll behavior is very awkward on my Mac (10.12.6). I prefer having my scroll direction on my trackpad to have Natural unchecked. With the scroll settings as such, when I try to scroll inside the datatable that lists all the selected marks (especially when trying to scroll horizontally), it behaves as if it is confused which way I am trying to scroll the contents. If I set my OS settings to have a Natural scroll direction then things do behave more sanely.

Publishing Extensions to the Extensions Server

I'm trying to view dashboards that contain extensions on the server client that I installed. I'm getting an error message and if I look at the traffic I get an internal server error (500). It looks like I'm missing a JS package (hide-load-indicators.js).

screen shot 2018-01-22 at 14 10 49

This is the server version I'm using:
screen shot 2018-01-22 at 16 57 02

Proposal: Server visibility into extensions usage

  • When publishing workbooks that contain Extensions, Tableau Server will 'register' those extensions to the Server repository.
  • There will be a new Server Admin View containing information about which Extensions are in use, which views/workbooks they are attached to, and how often they are loaded.
  • There will be a new tab in the Content->Workbook page that lists metadata about the Extension: Name of Extension, Extension Version, Author's Name, Author's Email address, Author's website, whitelist status.

Proposal: XSS Prevention Enforcement

We propose the following, and are interested in hearing your feedback:

  • Prevent inline javascript. This means you will have to keep your javascript logic in separate files from your html
  • Prevent loading of external (non-local) scripts. This means you will need to download any .js files you use in your web app and have the reference be to that local file.

Local http-server instance: Missing images and Broken Links

Working through:
https://tableau.github.io/extensions-api/docs/trex_getstarted.html

Section: Start a web server to host the sample dashboard extensions

This site will get you up and running with Tableau extensions.

I do not see how this locally running site will get anyone up and running if all most of the links are broken.

I followed the instruction to get these local site instances running:

  1. Multiple images and favicon are missing.
  2. Most of the visible and image-related links are broken.

screen shot 2018-05-20 at 10 25 12 am

$ npm start

> [email protected] start /Users/jefft/github/tableau/extensions-api
> node node_modules/http-server/bin/http-server -p 8765

Starting up http-server, serving ./
Available on:
  http://127.0.0.1:8765
  http://192.168.1.7:8765

Hit CTRL-C to stop the server
[Sun May 20 2018 10:20:22 GMT-0700 (PDT)] "GET /" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36"
[Sun May 20 2018 10:20:22 GMT-0700 (PDT)] "GET /%7B%7B%20site.baseurl%20%7D%7D/assets/docs.png" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36"
[Sun May 20 2018 10:20:22 GMT-0700 (PDT)] "GET /%7B%7B%20site.baseurl%20%7D%7D/assets/frelard_api3.png" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36"
[Sun May 20 2018 10:20:22 GMT-0700 (PDT)] "GET /%7B%7B%20site.baseurl%20%7D%7D/assets/docs.png" Error (404): "Not found"
[Sun May 20 2018 10:20:22 GMT-0700 (PDT)] "GET /%7B%7B%20site.baseurl%20%7D%7D/assets/frelard_api3.png" Error (404): "Not found"
[Sun May 20 2018 10:20:22 GMT-0700 (PDT)] "GET /%7B%7B%20site.baseurl%20%7D%7D/assets/flex.png" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36"
[Sun May 20 2018 10:20:22 GMT-0700 (PDT)] "GET /%7B%7B%20site.baseurl%20%7D%7D/assets/notes.png" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36"
[Sun May 20 2018 10:20:22 GMT-0700 (PDT)] "GET /%7B%7B%20site.baseurl%20%7D%7D/assets/flex.png" Error (404): "Not found"
[Sun May 20 2018 10:20:22 GMT-0700 (PDT)] "GET /%7B%7B%20site.baseurl%20%7D%7D/assets/notes.png" Error (404): "Not found"
[Sun May 20 2018 10:20:22 GMT-0700 (PDT)] "GET /favicon.ico" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36"
[Sun May 20 2018 10:20:22 GMT-0700 (PDT)] "GET /favicon.ico" Error (404): "Not found"

Followed your steps to install tableau extensions...

0 info it worked if it ends with ok
1 verbose cli [ 'C:\Program Files\nodejs\node.exe',
1 verbose cli 'C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js',
1 verbose cli 'install' ]
2 info using [email protected]
3 info using [email protected]
4 verbose stack Error: Cannot find module 'github-url-from-git'
4 verbose stack at Function.Module._resolveFilename (module.js:469:15)
4 verbose stack at Function.Module._load (module.js:417:25)
4 verbose stack at Module.require (module.js:497:17)
4 verbose stack at require (internal/module.js:20:19)
4 verbose stack at Object. (C:\Program Files\nodejs\node_modules\npm\node_modules\read-package-json\node_modules\normalize-package-data\lib\fixer.js:2:22)
4 verbose stack at Module._compile (module.js:570:32)
4 verbose stack at Object.Module._extensions..js (module.js:579:10)
4 verbose stack at Module.load (module.js:487:32)
4 verbose stack at tryModuleLoad (module.js:446:12)
4 verbose stack at Function.Module._load (module.js:438:3)
5 verbose cwd C:\Users\09137812\Documents\My Tableau Repository (Beta)\Extensions
6 error Windows_NT 6.1.7601
7 error argv "C:\Program Files\nodejs\node.exe" "C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js" "install"
8 error node v6.11.4
9 error npm v3.10.10
10 error code MODULE_NOT_FOUND
11 error Cannot find module 'github-url-from-git'
12 error If you need help, you may report this error at:
12 error https://github.com/npm/npm/issues
13 verbose exit [ 1, true ]

Proposal: Add sheet source to DataTable

When working with multiple getSummaryDataAsync (and underlying data) calls it would be super helpful to include the source sheet name in the returned DataTable object.

Proposal: Versioning

Below is the proposal for versioning. Please leave feedback.

  • Require semver (e.g. 1.3.2) in the extension manifest
  • Users will see different major versions of extensions in Tableau Desktop. However, only the latest minor version will show up
  • Because extensions are web apps, most changes will occur in the web app, not the manifest
  • Requests to your server will include a header with:
  1. API version
  2. Tableau version
  3. Extension version

Proposal: Redirects Restrictions Revised

  • Redirects are allowed
  • The API will only communicate with the same origin listed in the manifest
    • (Origin = protocal + domain + port)
    • API can communicate with other url's with the same origin

Summary data column data type returns nothing but strings

sheet.getSummaryDataAsync({ignoreSelection: true}).then((data) => {

The column meta data contained in data.columns[i] has the attribute dataType which presumably is supposed to return string, float, int, date, etc.

However it seems to always be returning the value 'string' even when it's obviously not a string type:
image

Bug with Tutorial and tableau-extensions-0.8.0.js

Hi, I'm attempting to learn how to write extensions and downloaded all the files, etc today. I got error messages from tutorial Part_1 onwards in tableau after adding the extension to a dashboard in tableau. When I changed tableau-extensions-0.8.0 to tableau-extensions-0.7.0 in the MarksSelection.html of each part, the error didn't appear and things started working in tableau. Anyway, I'm new to all this so debug is above my head, but letting yall know. Or maybe its an issue with my setup. Also, thanks for the tutorials, i hope to find the functionality i need in one of them and hack together the solution i need! -Fred

Ability to connect to the underneath source directly

Hi,
Current ConnectionSummary interface doesn't expose connection details of underneath source. If we want to access raw data only option is to use * getUnderlyingDataAsync* which may be too much load on node.js server memory. Is there any plans to add ability to pull data directly from the source?

Proposal: which filter is used as a quick-filter on a dashboard

DashboardObject type 'quick-filter' is missing a way to retrieve which filters these are.

For example worksheet has getFiltersAsync to retrieve filters used on the worksheet.

Use Case:
Customers use lots of filters on worksheets, some are used as technical filters others are used on the dashboard to filter. We call those user filters. But right now we can't retrieve those user filters. If I use worksheet->getFiltersAsync I get all filters. This information is not always relevant for the end user to see.

BUG: Extensions disappears when exporting to image or PDF

We are currently creating some additional Viz types with the Extensions API.
Really fun and it opens a tons of possibilities!

But when I tried to export my dashboard to PNG to show off my new Viz type it didnt render the Extension. I know this is the same for webpage parts but it would be create if the extensions can be exported in a image / PDF as an snapshot image for example.

Latest version of extensions always gives error

Have installed latest version of Tableau desktop (tableau-setup-std-main.18.0208.2310-x64).

Have also installed the latest extensions-api-master (the one including UI Namespace example)

Open Tableau desktop and connect to datasource "superstore"; you get immediately an error: Internal Error - An unexpected error occurred and the operation could not be completed.

Any idea whats going wrong ?
afbeelding

Parameter changeValueAsync with percentages expects comma instead of point

Reproducable example: try the Parameter.changeValueAsync method on the Superstore workbook to change the "Churn rate" parameter.

parameter.changeValueAsync(0.1); // 25%
parameter.changeValueAsync("0.1"); // 25%
parameter.changeValueAsync("0,1"); // 10%

This is especially confusing because it will return DataValue.value === "0.1" (point not comma πŸ˜–)

`getUnderlyingDataAsync()` and `getSummaryData()` returns all columns as `string`

When using getUnderlyingDataAsync in Tableau Desktop Beta build 17.0929.1346 the returned columns are always reported as having string dataType.

When testing with Superstore, calling (example code)

worksheet
    .getUnderlyingDataAsync({
        maxRows          : 0,
        includeAllColumns: true
     }).then( table => table.columns.forEach(c=>
         addToLog(`${c.name} : ${c.dataType}`)
     ));

results in:

...
Category : string
Order Date : string
Order Profitable? : string
...

Other Tableau workbooks also exhibit the same behaviour, as have previous versions of frelard.

Proposal: Security model

  • Extensions must declare, in the manifest, if they intend to access underlying data or datasource information. The API will enforce that if the Extension did not declare underlying data access, it will not be able to make those calls.
  • In Desktop, when adding a new Extension, if the Extension requests underlying data access, the user will be prompted to allow/disallow the Extension.
  • In Desktop, when opening an existing workbook, the user will be prompted. This prompt will inform the user if the Extension accesses underlying data access, and will ask the user to allow/disallow the Extension (whether it accesses underlying data or not).
  • In Server, in the site settings page, admins will control a list of safe-listed domains. Extensions that are from domains that are not in this safe-list will not load.
  • Each entry in the safe-list will have a checkbox to allow/disallow Underlying Data Access. Extensions that request Underlying Data Access, but that are not safe-listed for Underlying Data Access will not load.
  • Each entry in the safe-list will have a checkbox to suppress prompts. If an Extension is safe-listed but prompts are not suppresses, Server Interactors will be prompted when loading workbooks that contain those Extensions. If an Extension is safe-listed with suppress-prompts, Interactors will not be prompted.
  • The default for the safe-list is "https://*" ; No Underlying Data Access ; Do not Suppress Prompts. That is, all Extensions that do not request Underlying Data Access will work by default, but they will prompt. From there, admins can add domains that are allowed to access underlying data, or for which prompts should be suppressed. The admin can also delete this default entry to disallow all extensions (and then they can safe-list one-by-one).

Tableau Desktop Not Detecting all TREX files

I have a bunch of valid trex files in my Repo (Beta) Extensions folder, including some from the Samples folder but only two of them are being added to the extensions menu in Dekstop:

extensions

I've checked the log and there doesn't seem to be any reference to an invalid trex file. Saying that, no .trex files are mentioned in the logs at all. That could be useful to add for validation in the future

Case sensitivity in Samples folder names

On a Windows PC running the samples in Node does not cause a problem but if the samples are run on Linux (or Docker) then the trex file uses a lowercase case path to the samples while the folders themselves have uppercase. This means that the folders do not match. I am surprised this did not show up for Mac users - so I might be missing something.

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.