tryghost / algolia Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
The package concerned is algolia-fragmenter
specifically the transformToAlgoliaObject function.
Currently, the algoliaPost
is hardcoded and the function does not offer any way to add additional fields. It will be interesting to add an optional argument to transformToAlgoliaObject which will help to extend the algoliaPost
.
I noticed that the check here: https://github.com/TryGhost/algolia/blob/master/packages/algolia-netlify/functions/post-published.js#L5
Is incorrect, it's casting the environment variable to a boolean, and then comparing that with a string, so this will never evaluate to true!
It might be better to change it to:
if (process.env.ALGOLIA_ACTIVE !== 'TRUE') {
I tried to deploy this repository into Netlify using the button in the README.md, but the deployment failed. I'm attaching the deployment log below.
8:44:53 PM: Build ready to start
8:44:54 PM: build-image version: fa439ad1ab9393b2c0d449d8d7c033927683f4b0
8:44:54 PM: build-image tag: v4.3.0
8:44:54 PM: buildbot version: bfa1ece451875e5fe124c5b0a59bb85e0abb8d50
8:44:55 PM: Fetching cached dependencies
8:44:55 PM: Failed to fetch cache, continuing with build
8:44:55 PM: Starting to prepare the repo for build
8:44:55 PM: No cached dependencies found. Cloning fresh repo
8:44:55 PM: git clone https://github.com/TryGhost/algolia
8:44:56 PM: Preparing Git Reference refs/heads/main
8:44:56 PM: Parsing package.json dependencies
8:44:56 PM: Different build dir detected, going to use the one specified in the Netlify configuration file: 'packages/algolia-netlify' versus '' in the Netlify UI
8:44:56 PM: Different publish path detected, going to use the one specified in the Netlify configuration file: 'packages/algolia-netlify/dist' versus 'dist/' in the Netlify UI
8:44:56 PM: Different functions path detected, going to use the one specified in the Netlify configuration file: 'packages/algolia-netlify/build/functions' versus 'build/functions' in the Netlify UI
8:44:57 PM: Starting build script
8:44:57 PM: Installing dependencies
8:44:57 PM: Python version set to 2.7
8:44:57 PM: Attempting node version '14' from .nvmrc
8:44:58 PM: Downloading and installing node v14.17.6...
8:44:58 PM: Downloading https://nodejs.org/dist/v14.17.6/node-v14.17.6-linux-x64.tar.xz...
8:44:58 PM: Computing checksum with sha256sum
8:44:58 PM: Checksums matched!
8:45:01 PM: Now using node v14.17.6 (npm v6.14.15)
8:45:01 PM: Started restoring cached build plugins
8:45:01 PM: Finished restoring cached build plugins
8:45:01 PM: Attempting ruby version 2.7.2, read from environment
8:45:03 PM: Using ruby version 2.7.2
8:45:03 PM: Using PHP version 8.0
8:45:03 PM: Started restoring cached yarn cache
8:45:03 PM: Finished restoring cached yarn cache
8:45:03 PM: Installing yarn at version 1.22.10
8:45:03 PM: Installing Yarn!
8:45:03 PM: > Downloading tarball...
8:45:03 PM: [1/2]: https://yarnpkg.com/downloads/1.22.10/yarn-v1.22.10.tar.gz --> /tmp/yarn.tar.gz.myZSuSeWdv
8:45:03 PM: % Total % Received % Xferd Average Speed Time Time Time Current
8:45:03 PM: Dload Upload Total Spent Left Speed
8:45:03 PM: 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
8:45:03 PM: 100 81 100 81 0 0 627 0 --:--:-- --:--:-- --:--:-- 627
8:45:03 PM: 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
8:45:03 PM: 100 95 100 95 0 0 248 0 --:--:-- --:--:-- --:--:-- 470
8:45:04 PM: 100 626 100 626 0 0 1282 0 --:--:-- --:--:-- --:--:-- 1282
8:45:04 PM: 100 1215k 100 1215k 0 0 2026k 0 --:--:-- --:--:-- --:--:-- 2026k
8:45:04 PM: [2/2]: https://yarnpkg.com/downloads/1.22.10/yarn-v1.22.10.tar.gz.asc --> /tmp/yarn.tar.gz.myZSuSeWdv.asc
8:45:04 PM: % Total % Received % Xferd Average Speed Time Time Time Current
8:45:04 PM: Dload Upload Total Spent Left Speed
8:45:04 PM: 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
8:45:04 PM: 100 85 100 85 0 0 1416 0 --:--:-- --:--:-- --:--:-- 1416
8:45:04 PM: 100 99 100 99 0 0 1112 0 --:--:-- --:--:-- --:--:-- 1112
8:45:04 PM: 100 630 100 630 0 0 2763 0 --:--:-- --:--:-- --:--:-- 2763
8:45:04 PM: 100 832 100 832 0 0 2919 0 --:--:-- --:--:-- --:--:-- 2919
8:45:04 PM: > Verifying integrity...
8:45:04 PM: gpg: Signature made Fri 02 Oct 2020 11:17:27 AM UTC
8:45:04 PM: gpg: using RSA key 6D98490C6F1ACDDD448E45954F77679369475BAA
8:45:04 PM: gpg: Good signature from "Yarn Packaging <[email protected]>" [unknown]
8:45:04 PM: gpg: WARNING: This key is not certified with a trusted signature!
8:45:04 PM: gpg: There is no indication that the signature belongs to the owner.
8:45:04 PM: Primary key fingerprint: 72EC F46A 56B4 AD39 C907 BBB7 1646 B01B 86E5 0310
8:45:04 PM: Subkey fingerprint: 6D98 490C 6F1A CDDD 448E 4595 4F77 6793 6947 5BAA
8:45:04 PM: > GPG signature looks good
8:45:04 PM: > Extracting to ~/.yarn...
8:45:04 PM: > Adding to $PATH...
8:45:04 PM: > Successfully installed Yarn 1.22.10! Please open another terminal where the `yarn` command will now be available.
8:45:05 PM: Yarn workspaces detected
8:45:05 PM: Installing NPM modules using Yarn version 1.22.10
8:45:06 PM: yarn install v1.22.10
8:45:06 PM: [1/4] Resolving packages...
8:45:06 PM: [2/4] Fetching packages...
8:45:26 PM: info [email protected]: The platform "linux" is incompatible with this module.
8:45:26 PM: info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
8:45:26 PM: info [email protected]: The platform "linux" is incompatible with this module.
8:45:26 PM: info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
8:45:26 PM: [3/4] Linking dependencies...
8:45:35 PM: [4/4] Building fresh packages...
8:45:36 PM: $ netlify-lambda install functions
8:45:36 PM: netlify-lambda: installing function dependencies
8:45:36 PM: Done in 30.67s.
8:45:36 PM: NPM modules installed using Yarn
8:45:37 PM: Started restoring cached go cache
8:45:37 PM: Finished restoring cached go cache
8:45:37 PM: go version go1.16.5 linux/amd64
8:45:37 PM: go version go1.16.5 linux/amd64
8:45:37 PM: Installing missing commands
8:45:37 PM: Verify run directory
8:45:38 PM:
8:45:38 PM: ────────────────────────────────────────────────────────────────
8:45:38 PM: Netlify Build
8:45:38 PM: ────────────────────────────────────────────────────────────────
8:45:38 PM:
8:45:38 PM: ❯ Version
8:45:38 PM: @netlify/build 18.8.0
8:45:38 PM:
8:45:38 PM: ❯ Flags
8:45:38 PM: baseRelDir: true
8:45:38 PM: buildId: 613b766de092cdfaa40e4bba
8:45:38 PM: deployId: 613b766de092cdfaa40e4bbc
8:45:38 PM:
8:45:38 PM: ❯ Current directory
8:45:38 PM: /opt/build/repo/packages/algolia-netlify
8:45:38 PM:
8:45:38 PM: ❯ Config file
8:45:38 PM: /opt/build/repo/packages/algolia-netlify/netlify.toml
8:45:38 PM:
8:45:38 PM: ❯ Context
8:45:38 PM: production
8:45:38 PM:
8:45:38 PM: ────────────────────────────────────────────────────────────────
8:45:38 PM: 1. build.command from netlify.toml
8:45:38 PM: ────────────────────────────────────────────────────────────────
8:45:38 PM:
8:45:38 PM: $ NODE_ENV=production yarn build
8:45:38 PM: yarn run v1.22.10
8:45:38 PM: $ netlify-lambda build functions
8:45:39 PM: netlify-lambda: Building functions
8:46:00 PM: Hash: 7e54c5963f76c7fc3e13
8:46:00 PM: Version: webpack 4.46.0
8:46:00 PM: Time: 20567ms
8:46:00 PM: Built at: 09/10/2021 3:16:00 PM
8:46:00 PM: Asset Size Chunks Chunk Names
8:46:00 PM: post-published.js 2.71 MiB 0 [emitted] post-published
8:46:00 PM: post-unpublished.js 38.8 KiB 1 [emitted] post-unpublished
8:46:00 PM: Entrypoint post-published = post-published.js
8:46:00 PM: Entrypoint post-unpublished = post-unpublished.js
8:46:00 PM: [2] /opt/build/repo/node_modules/@algolia/client-common/dist/client-common.esm.js 2.73 KiB {0} {1} [built]
8:46:00 PM: [7] /opt/build/repo/node_modules/@algolia/transporter/dist/transporter.esm.js 17.9 KiB {0} {1} [built]
8:46:00 PM: [10] external "crypto" 42 bytes {0} {1} [built]
8:46:00 PM: [111] /opt/build/repo/packages/algolia-indexer/index.js 47 bytes {0} {1} [built]
8:46:00 PM: [112] /opt/build/repo/packages/algolia-indexer/lib/IndexFactory.js 2.93 KiB {0} {1} [built]
8:46:00 PM: [113] /opt/build/repo/node_modules/algoliasearch/index.js 605 bytes {0} {1} [built]
8:46:00 PM: [114] /opt/build/repo/node_modules/algoliasearch/dist/algoliasearch.cjs.js 7.85 KiB {0} {1} [built]
8:46:00 PM: [115] /opt/build/repo/node_modules/@algolia/cache-common/dist/cache-common.esm.js 1.77 KiB {0} {1} [built]
8:46:00 PM: [116] /opt/build/repo/node_modules/@algolia/cache-in-memory/dist/cache-in-memory.esm.js 1.24 KiB {0} {1} [built]
8:46:00 PM: [336] ./post-published.js 1.64 KiB {0} [built]
8:46:00 PM: [337] /opt/build/repo/packages/algolia-fragmenter/index.js 46 bytes {0} [built]
8:46:00 PM: [338] /opt/build/repo/packages/algolia-fragmenter/lib/transformer.js 4.77 KiB {0} [built]
8:46:00 PM: [339] /opt/build/repo/node_modules/algolia-html-extractor/index.js 108 bytes {0} [built]
8:46:00 PM: [340] /opt/build/repo/node_modules/algolia-html-extractor/lib/algoliaHtmlExtractor.js 4.96 KiB {0} [built]
8:46:00 PM: [767] ./post-unpublished.js 1.39 KiB {1} [built]
8:46:00 PM: + 753 hidden modules
8:46:00 PM: WARNING in /opt/build/repo/node_modules/jsdom/lib/jsdom/utils.js 186:21-40
8:46:00 PM: Critical dependency: the request of a dependency is an expression
8:46:00 PM: @ /opt/build/repo/node_modules/jsdom/lib/jsdom/browser/Window.js
8:46:00 PM: @ /opt/build/repo/node_modules/jsdom/lib/api.js
8:46:00 PM: @ /opt/build/repo/node_modules/algolia-html-extractor/lib/algoliaHtmlExtractor.js
8:46:00 PM: @ /opt/build/repo/node_modules/algolia-html-extractor/index.js
8:46:00 PM: @ /opt/build/repo/packages/algolia-fragmenter/lib/transformer.js
8:46:00 PM: @ /opt/build/repo/packages/algolia-fragmenter/index.js
8:46:00 PM: @ ./post-published.js
8:46:00 PM: WARNING in /opt/build/repo/node_modules/parse5/lib/index.js 55:23-49
8:46:00 PM: Critical dependency: the request of a dependency is an expression
8:46:00 PM: @ /opt/build/repo/node_modules/jsdom/lib/jsdom/browser/domtohtml.js
8:46:00 PM: @ /opt/build/repo/node_modules/jsdom/lib/api.js
8:46:00 PM: @ /opt/build/repo/node_modules/algolia-html-extractor/lib/algoliaHtmlExtractor.js
8:46:00 PM: @ /opt/build/repo/node_modules/algolia-html-extractor/index.js
8:46:00 PM: @ /opt/build/repo/packages/algolia-fragmenter/lib/transformer.js
8:46:00 PM: @ /opt/build/repo/packages/algolia-fragmenter/index.js
8:46:00 PM: @ ./post-published.js
8:46:00 PM: WARNING in /opt/build/repo/node_modules/ws/lib/buffer-util.js
8:46:00 PM: Module not found: Error: Can't resolve 'bufferutil' in '/opt/build/repo/node_modules/ws/lib' @ /opt/build/repo/node_modules/ws/lib/buffer-util.js
8:46:00 PM: @ /opt/build/repo/node_modules/ws/lib/sender.js
8:46:00 PM: @ /opt/build/repo/node_modules/ws/index.js
8:46:00 PM: @ /opt/build/repo/node_modules/jsdom/lib/jsdom/living/websockets/WebSocket-impl.js
8:46:00 PM: @ /opt/build/repo/node_modules/jsdom/lib/jsdom/browser/Window.js
8:46:00 PM: @ /opt/build/repo/node_modules/jsdom/lib/api.js
8:46:00 PM: @ /opt/build/repo/node_modules/algolia-html-extractor/lib/algoliaHtmlExtractor.js
8:46:00 PM: @ /opt/build/repo/node_modules/algolia-html-extractor/index.js
8:46:00 PM: @ /opt/build/repo/packages/algolia-fragmenter/lib/transformer.js
8:46:00 PM: @ /opt/build/repo/packages/algolia-fragmenter/index.js
8:46:00 PM: @ ./post-published.js
8:46:00 PM: WARNING in /opt/build/repo/node_modules/ws/lib/validation.js
8:46:00 PM: Module not found: Error: Can't resolve 'utf-8-validate' in '/opt/build/repo/node_modules/ws/lib' @ /opt/build/repo/node_modules/ws/lib/validation.js
8:46:00 PM: @ /opt/build/repo/node_modules/ws/lib/sender.js
8:46:00 PM: @ /opt/build/repo/node_modules/ws/index.js
8:46:00 PM: @ /opt/build/repo/node_modules/jsdom/lib/jsdom/living/websockets/WebSocket-impl.js
8:46:00 PM: @ /opt/build/repo/node_modules/jsdom/lib/jsdom/browser/Window.js
8:46:00 PM: @ /opt/build/repo/node_modules/jsdom/lib/api.js
8:46:00 PM: @ /opt/build/repo/node_modules/algolia-html-extractor/lib/algoliaHtmlExtractor.js
8:46:00 PM: @ /opt/build/repo/node_modules/algolia-html-extractor/index.js
8:46:00 PM: @ /opt/build/repo/packages/algolia-fragmenter/lib/transformer.js
8:46:00 PM: @ /opt/build/repo/packages/algolia-fragmenter/index.js
8:46:00 PM: @ ./post-published.js
8:46:00 PM: Done in 21.54s.
8:46:00 PM:
8:46:00 PM: (build.command completed in 21.7s)
8:46:00 PM:
8:46:00 PM: ────────────────────────────────────────────────────────────────
8:46:00 PM: 2. Functions bundling
8:46:00 PM: ────────────────────────────────────────────────────────────────
8:46:00 PM:
8:46:00 PM: Packaging Functions from build/functions directory:
8:46:00 PM: - post-published.js
8:46:00 PM: - post-unpublished.js
8:46:00 PM:
8:46:07 PM:
8:46:07 PM: (Functions bundling completed in 7s)
8:46:07 PM:
8:46:07 PM: ────────────────────────────────────────────────────────────────
8:46:07 PM: 3. Deploy site
8:46:07 PM: ────────────────────────────────────────────────────────────────
8:46:07 PM:
8:46:07 PM:
8:46:07 PM: ────────────────────────────────────────────────────────────────
8:46:07 PM: Configuration error
8:46:07 PM: ────────────────────────────────────────────────────────────────
8:46:07 PM:
8:46:07 PM: Error message
8:46:07 PM: Deploy did not succeed: Deploy directory 'packages/algolia-netlify/dist' does not exist
8:46:07 PM:
8:46:07 PM: Resolved config
8:46:07 PM: build:
8:46:07 PM: base: /opt/build/repo/packages/algolia-netlify
8:46:07 PM: command: NODE_ENV=production yarn build
8:46:07 PM: commandOrigin: config
8:46:07 PM: environment:
8:46:07 PM: - ALGOLIA_ACTIVE
8:46:07 PM: - ALGOLIA_API_KEY
8:46:07 PM: - ALGOLIA_APP_ID
8:46:07 PM: - ALGOLIA_INDEX
8:46:07 PM: - NODE_VERSION
8:46:07 PM: - AWS_LAMBDA_JS_RUNTIME
8:46:07 PM: publish: /opt/build/repo/packages/algolia-netlify/dist
8:46:07 PM: publishOrigin: ui
8:46:07 PM: functionsDirectory: /opt/build/repo/packages/algolia-netlify/build/functions
8:46:07 PM: Caching artifacts
8:46:07 PM: Started saving workspace packages/algolia-fragmenter node modules
8:46:07 PM: Finished saving workspace packages/algolia-fragmenter node modules
8:46:07 PM: Started saving workspace packages/algolia-indexer node modules
8:46:07 PM: Finished saving workspace packages/algolia-indexer node modules
8:46:07 PM: Started saving workspace packages/algolia-netlify node modules
8:46:07 PM: Finished saving workspace packages/algolia-netlify node modules
8:46:07 PM: Started saving workspace packages/algolia node modules
8:46:07 PM: Finished saving workspace packages/algolia node modules
8:46:07 PM: Started saving workspace root node modules
8:46:07 PM: Finished saving workspace root node modules
8:46:07 PM: Started saving build plugins
8:46:07 PM: Finished saving build plugins
8:46:07 PM: Started saving yarn cache
8:46:10 PM: Finished saving yarn cache
8:46:10 PM: Started saving pip cache
8:46:10 PM: Finished saving pip cache
8:46:10 PM: Started saving emacs cask dependencies
8:46:10 PM: Finished saving emacs cask dependencies
8:46:10 PM: Started saving maven dependencies
8:46:11 PM: Finished saving maven dependencies
8:46:11 PM: Started saving boot dependencies
8:46:11 PM: Finished saving boot dependencies
8:46:11 PM: Started saving rust rustup cache
8:46:11 PM: Finished saving rust rustup cache
8:46:11 PM: Started saving go dependencies
8:46:11 PM: Finished saving go dependencies
8:46:13 PM: Build failed due to a user error: Build script returned non-zero exit code: 2
8:46:13 PM: Creating deploy upload records
8:46:13 PM: Failing build: Failed to build site
8:46:13 PM: Failed during stage 'building site': Build script returned non-zero exit code: 2
8:46:13 PM: Finished processing build request in 1m18.904129732s
Since IndexFactory.setSettingsForIndex()
allows optional update, creating an Algolia index doesn't work using https://github.com/TryGhost/algolia/tree/main/packages/algolia . The process exits with this error:
error Error saving fragments [
TypeError: Cannot read properties of undefined (reading 'updateSettings')
at IndexFactory.setSettingsForIndex (node_modules/@tryghost/algolia-indexer/lib/IndexFactory.js:98:32)
at TypeCommand.run [as _runHandler] (node_modules/@tryghost/algolia/bin/cli.js:125:25)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async Promise.all (index 2)
]
It seems that the issue is either in the signature for setSettingsForIndex
method by requiring an object as an argument instead of boolean, or that the argument is not supplied in https://github.com/TryGhost/algolia/blob/main/packages/algolia/bin/cli.js#L125C29-L125C29
Which makes me wonder if it's active and ever used at all.
The @tryghost/algolia
package requires @tryghost/algolia-indexer
which is not listed in its dependencies. That makes the CLI instantly fail unless I install this dependency next to it manually.
This line https://github.com/TryGhost/algolia/blob/main/packages/algolia-fragmenter/lib/transformer.js#L106 assumes the presence of the authors
array. Apparently, it's not sent anymore, at least for the Published/Updated event. Which is a problem per se, of course.
I have observed this issue in prod (hosted Ghost) and reproduced it locally.
Right now although the searchable attributes are specified in the config file they are still hardcoded in algolia-indexer and algolia fragmenter. So what should be the right thing would be to use the values from the config file when constructing the object to pass to algolia.
11:19:38 AM: ────────────────────────────────────────────────────────────────
11:19:38 AM: Configuration error
11:19:38 AM: ────────────────────────────────────────────────────────────────
11:19:38 AM:
11:19:38 AM: Error message
11:19:38 AM: Deploy did not succeed: Deploy directory 'packages/algolia-netlify/dist' does not exist
11:19:38 AM:
11:19:38 AM: Resolved config
11:19:38 AM: build:
11:19:38 AM: base: /opt/build/repo/packages/algolia-netlify
11:19:38 AM: command: NODE_ENV=production yarn build
11:19:38 AM: commandOrigin: config
11:19:38 AM: environment:
11:19:38 AM: - ALGOLIA_ACTIVE
11:19:38 AM: - ALGOLIA_API_KEY
11:19:38 AM: - ALGOLIA_APP_ID
11:19:38 AM: - ALGOLIA_INDEX
11:19:38 AM: - NODE_VERSION
11:19:38 AM: - AWS_LAMBDA_JS_RUNTIME
11:19:38 AM: publish: /opt/build/repo/packages/algolia-netlify/dist
11:19:38 AM: publishOrigin: ui
11:19:38 AM: functionsDirectory: /opt/build/repo/packages/algolia-netlify/build/functions
11:19:39 AM: Caching artifacts
In cli.js the original code is:
let context = {errors: [], posts: []};
. . .
context.posts = await ghost.posts.browse();
… which obviously fetches posts. However, changing the second line above to:
context.posts = await ghost.pages.browse();
… still fetches posts.
Is this hard-wired somewhere? Really should be able to fetch and index pages as well.
This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
These problems occurred while renovating this repository. View logs.
These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
eslint
, eslint-plugin-import
, mocha
).github/workflows/test.yml
actions/checkout v4
actions/setup-node v3
package.json
eslint 8.54.0
eslint-plugin-ghost 3.4.0
mocha 10.2.0
should 13.2.3
sinon 17.0.1
packages/algolia-fragmenter/package.json
algolia-html-extractor 0.0.1
mocha 10.2.0
should 13.2.3
sinon 17.0.1
packages/algolia-indexer/package.json
@tryghost/errors 1.2.27
algoliasearch 4.20.0
mocha 10.2.0
should 13.2.3
sinon 17.0.1
packages/algolia-netlify/package.json
eslint 8.54.0
eslint-config-airbnb-base 15.0.0
eslint-plugin-ghost 3.4.0
eslint-plugin-import 2.29.0
mocha 10.2.0
netlify-cli 16.3.1
should 13.2.3
sinon 17.0.1
packages/algolia/package.json
@tryghost/content-api 1.11.20
@tryghost/errors 1.2.27
@tryghost/pretty-cli 1.2.39
fs-extra 11.1.1
mocha 10.2.0
should 13.2.3
sinon 17.0.1
.nvmrc
node 18
packages/algolia-netlify/.nvmrc
node 18
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.