feat: Updates to search indices (#32)

This commit is contained in:
Vlad Hashimoto 2019-05-22 19:00:32 +03:00 коммит произвёл Michelle Tilley
Родитель 39fdff22bf
Коммит 8acc4391b3
15 изменённых файлов: 48395 добавлений и 2884 удалений

3
.gitignore поставляемый
Просмотреть файл

@ -1,3 +1,4 @@
.env
.npmrc
node_modules
node_modules
*.log

21776
dist/apis.json поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

8766
dist/apps.json поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

214
dist/glossary.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,214 @@
{
"name": "glossary",
"records": [
{
"objectID": "glossary-ASAR",
"term": "ASAR",
"description": "ASAR stands for Atom Shell Archive Format. An asar archive is a simple tar-like format that concatenates files into a single file. Electron can read arbitrary files from it without unpacking the whole file.",
"url": "https://electronjs.org/docs/glossary#asar",
"keyValuePairs": [
"is:doc",
"is:glossary",
"glossary:ASAR"
]
},
{
"objectID": "glossary-CRT",
"term": "CRT",
"description": "The C Run-time Library (CRT) is the part of the C++ Standard Library that incorporates the ISO C99 standard library. The Visual C++ libraries that implement the CRT support native code development, and both mixed native and managed code, and pure managed code for .NET development.",
"url": "https://electronjs.org/docs/glossary#crt",
"keyValuePairs": [
"is:doc",
"is:glossary",
"glossary:CRT"
]
},
{
"objectID": "glossary-DMG",
"term": "DMG",
"description": "An Apple Disk Image is a packaging format used by macOS. DMG files are commonly used for distributing application \"installers\". electron-builder supports dmg as a build target.",
"url": "https://electronjs.org/docs/glossary#dmg",
"keyValuePairs": [
"is:doc",
"is:glossary",
"glossary:DMG"
]
},
{
"objectID": "glossary-IME",
"term": "IME",
"description": "Input Method Editor. A program that allows users to enter characters and symbols not found on their keyboard. For example, this allows users of Latin keyboards to input Chinese, Japanese, Korean and Indic characters.",
"url": "https://electronjs.org/docs/glossary#ime",
"keyValuePairs": [
"is:doc",
"is:glossary",
"glossary:IME"
]
},
{
"objectID": "glossary-IDL",
"term": "IDL",
"description": "Interface description language. Write function signatures and data types in a format that can be used to generate interfaces in Java, C++, JavaScript, etc.",
"url": "https://electronjs.org/docs/glossary#idl",
"keyValuePairs": [
"is:doc",
"is:glossary",
"glossary:IDL"
]
},
{
"objectID": "glossary-IPC",
"term": "IPC",
"description": "IPC stands for Inter-Process Communication. Electron uses IPC to send serialized JSON messages between the main and renderer processes.",
"url": "https://electronjs.org/docs/glossary#ipc",
"keyValuePairs": [
"is:doc",
"is:glossary",
"glossary:IPC"
]
},
{
"objectID": "glossary-libchromiumcontent",
"term": "libchromiumcontent",
"description": "A shared library that includes the Chromium Content module and all its dependencies (e.g., Blink, V8, etc.). Also referred to as \"libcc\".",
"url": "https://electronjs.org/docs/glossary#libchromiumcontent",
"keyValuePairs": [
"is:doc",
"is:glossary",
"glossary:libchromiumcontent"
]
},
{
"objectID": "glossary-main process",
"term": "main process",
"description": "The main process, commonly a file named main.js, is the entry point to every Electron app. It controls the life of the app, from open to close. It also manages native elements such as the Menu, Menu Bar, Dock, Tray, etc. The main process is responsible for creating each new renderer process in the app. The full Node API is built in.",
"url": "https://electronjs.org/docs/glossary#main-process",
"keyValuePairs": [
"is:doc",
"is:glossary",
"glossary:main process"
]
},
{
"objectID": "glossary-MAS",
"term": "MAS",
"description": "Acronym for Apple's Mac App Store. For details on submitting your app to the MAS, see the Mac App Store Submission Guide.",
"url": "https://electronjs.org/docs/glossary#mas",
"keyValuePairs": [
"is:doc",
"is:glossary",
"glossary:MAS"
]
},
{
"objectID": "glossary-Mojo",
"term": "Mojo",
"description": "An IPC system for communicating intra- or inter-process, and that's important because Chrome is keen on being able to split its work into separate processes or not, depending on memory pressures etc.",
"url": "https://electronjs.org/docs/glossary#mojo",
"keyValuePairs": [
"is:doc",
"is:glossary",
"glossary:Mojo"
]
},
{
"objectID": "glossary-native modules",
"term": "native modules",
"description": "Native modules (also called addons in Node.js) are modules written in C or C++ that can be loaded into Node.js or Electron using the require() function, and used as if they were an ordinary Node.js module. They are used primarily to provide an interface between JavaScript running in Node.js and C/C++ libraries.",
"url": "https://electronjs.org/docs/glossary#native-modules",
"keyValuePairs": [
"is:doc",
"is:glossary",
"glossary:native modules"
]
},
{
"objectID": "glossary-NSIS",
"term": "NSIS",
"description": "Nullsoft Scriptable Install System is a script-driven Installer authoring tool for Microsoft Windows. It is released under a combination of free software licenses, and is a widely-used alternative to commercial proprietary products like InstallShield. electron-builder supports NSIS as a build target.",
"url": "https://electronjs.org/docs/glossary#nsis",
"keyValuePairs": [
"is:doc",
"is:glossary",
"glossary:NSIS"
]
},
{
"objectID": "glossary-OSR",
"term": "OSR",
"description": "OSR (Off-screen rendering) can be used for loading heavy page in background and then displaying it after (it will be much faster). It allows you to render page without showing it on screen.",
"url": "https://electronjs.org/docs/glossary#osr",
"keyValuePairs": [
"is:doc",
"is:glossary",
"glossary:OSR"
]
},
{
"objectID": "glossary-process",
"term": "process",
"description": "A process is an instance of a computer program that is being executed. Electron apps that make use of the main and one or many renderer process are actually running several programs simultaneously.",
"url": "https://electronjs.org/docs/glossary#process",
"keyValuePairs": [
"is:doc",
"is:glossary",
"glossary:process"
]
},
{
"objectID": "glossary-renderer process",
"term": "renderer process",
"description": "The renderer process is a browser window in your app. Unlike the main process, there can be multiple of these and each is run in a separate process. They can also be hidden.",
"url": "https://electronjs.org/docs/glossary#renderer-process",
"keyValuePairs": [
"is:doc",
"is:glossary",
"glossary:renderer process"
]
},
{
"objectID": "glossary-Squirrel",
"term": "Squirrel",
"description": "Squirrel is an open-source framework that enables Electron apps to update automatically as new versions are released. See the autoUpdater API for info about getting started with Squirrel.",
"url": "https://electronjs.org/docs/glossary#squirrel",
"keyValuePairs": [
"is:doc",
"is:glossary",
"glossary:Squirrel"
]
},
{
"objectID": "glossary-userland",
"term": "userland",
"description": "This term originated in the Unix community, where \"userland\" or \"userspace\" referred to programs that run outside of the operating system kernel. More recently, the term has been popularized in the Node and npm community to distinguish between the features available in \"Node core\" versus packages published to the npm registry by the much larger \"user\" community.",
"url": "https://electronjs.org/docs/glossary#userland",
"keyValuePairs": [
"is:doc",
"is:glossary",
"glossary:userland"
]
},
{
"objectID": "glossary-V8",
"term": "V8",
"description": "V8 is Google's open source JavaScript engine. It is written in C++ and is used in Google Chrome. V8 can run standalone, or can be embedded into any C++ application.",
"url": "https://electronjs.org/docs/glossary#v8",
"keyValuePairs": [
"is:doc",
"is:glossary",
"glossary:V8"
]
},
{
"objectID": "glossary-webview",
"term": "webview",
"description": "webview tags are used to embed 'guest' content (such as external web pages) in your Electron app. They are similar to iframes, but differ in that each webview runs in a separate process. It doesn't have the same permissions as your web page and all interactions between your app and embedded content will be asynchronous. This keeps your app safe from the embedded content.",
"url": "https://electronjs.org/docs/glossary#webview",
"keyValuePairs": [
"is:doc",
"is:glossary",
"glossary:webview"
]
}
]
}

200
dist/tutorials.json поставляемый

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -9,17 +9,43 @@ function getRecords () {
apis.forEach(api => {
// TODO constructorMethod
// TODO properties
// TODO instanceProperties
const properties = api.properties || []
properties.forEach(property => {
property.apiType = 'properties'
property.fullSignature = `${api.name}.${property.name}`
property.tldr = getTLDR(property)
property.slug = slugger.slug(property.fullSignature, false)
property.url = `https://electronjs.org/docs/api/${api.slug}#${property.slug}`
records.push(property)
})
const instanceProperties = api.instanceProperties || []
instanceProperties.forEach(property => {
property.apiType = 'instanceProperties'
property.fullSignature = `${api.name}.${property.name}`
property.tldr = getTLDR(property)
property.slug = slugger.slug(property.fullSignature, false)
property.url = `https://electronjs.org/docs/api/${api.slug}#${property.slug}`
records.push(property)
})
const methods = api.methods || []
methods.forEach(method => {
method.apiType = 'methods'
method.fullSignature = `${api.name}.${method.name}`
method.tldr = getTLDR(method)
method.slug = slugger.slug(method.fullSignature, false)
method.url = `https://electronjs.org/docs/api/${api.slug}#${method.slug}`
records.push(method)
})
const staticMethods = api.staticMethods || []
staticMethods.forEach(method => {
method.apiType = 'staticMethod'
method.fullSignature = `${api.name}.${method.name}${method.signature}`
method.tldr = getTLDR(method)
method.slug = slugger.slug(method.fullSignature)
method.slug = slugger.slug(method.fullSignature, false)
method.url = `https://electronjs.org/docs/api/${api.slug}#${method.slug}`
delete method.signature
records.push(method)
})
@ -28,9 +54,8 @@ function getRecords () {
method.apiType = 'instanceMethod'
method.fullSignature = `${api.instanceName}.${method.name}${method.signature}`
method.tldr = getTLDR(method)
method.slug = slugger.slug(method.fullSignature)
method.slug = slugger.slug(method.fullSignature, false)
method.url = `https://electronjs.org/docs/api/${api.slug}#${method.slug}`
delete method.signature
records.push(method)
})
@ -39,6 +64,7 @@ function getRecords () {
event.apiType = 'event'
event.fullSignature = `${api.name}.on('${event.name}')`
event.url = `https://electronjs.org/docs/api/${api.slug}#event-${event.name}`
event.slug = slugger.slug(event.fullSignature, false)
event.tldr = getTLDR(event)
records.push(event)
})
@ -48,6 +74,7 @@ function getRecords () {
event.apiType = 'event'
event.fullSignature = `${api.instanceName}.on('${event.name}')`
event.url = `https://electronjs.org/docs/api/${api.slug}#event-${event.name}`
event.slug = slugger.slug(event.fullSignature, false)
event.tldr = getTLDR(event)
records.push(event)
})
@ -66,7 +93,7 @@ function getRecords () {
]
return Object.assign(
{objectID: record.url.replace('https://electronjs.org/docs/api/', 'api-')},
{ objectID: record.url.replace('https://electronjs.org/docs/api/', 'api-') },
record
)
})

Просмотреть файл

@ -17,7 +17,7 @@ function getRecords () {
]
return Object.assign(
{objectID: `app-${app.slug}`},
{ objectID: `app-${app.slug}` },
app
)
})

29
indices/glossary.js Normal file
Просмотреть файл

@ -0,0 +1,29 @@
const { chain } = require('lodash')
const AlgoliaIndex = require('../lib/algolia-index')
module.exports = new AlgoliaIndex('glossary', getRecords())
function getRecords () {
return chain(Object.values(require('electron-i18n').glossary['en-US']))
.map(glossary => {
const { term, description } = glossary
const objectID = `glossary-${term}`
const keyValuePairs = [
'is:doc',
'is:glossary',
`glossary:${term}`
]
const url = `https://electronjs.org/docs/glossary#${term.toLowerCase()}`.replace(/ /g, '-')
return {
objectID,
term,
description,
url,
keyValuePairs
}
})
.compact() // remove nulls from early returns above
.value()
}

Просмотреть файл

@ -1,4 +1,4 @@
const {pick} = require('lodash')
const { pick } = require('lodash')
const packages = require('electron-npm-packages')
const AlgoliaIndex = require('../lib/algolia-index')
const props = 'name description sourcerank repository keywords license homepage owners created modified dependencies devDependencies scripts'.split(' ')
@ -8,7 +8,7 @@ module.exports = new AlgoliaIndex('packages', getRecords())
function getRecords () {
return packages.map(pkg => {
pkg = Object.assign(
{objectID: `package-${pkg.name}`},
{ objectID: `package-${pkg.name}` },
pick(pkg, props)
)
@ -24,7 +24,7 @@ function getRecords () {
]
if (Array.isArray(pkg.owners)) {
pkg.owners.forEach(({name}) => {
pkg.owners.forEach(({ name }) => {
if (!name) return
pkg.keyValuePairs.push(`owner:${name}`)
pkg.keyValuePairs.push(`author:${name}`)

Просмотреть файл

@ -1,4 +1,4 @@
const {chain} = require('lodash')
const { chain } = require('lodash')
const cheerio = require('cheerio')
const AlgoliaIndex = require('../lib/algolia-index')
@ -8,7 +8,7 @@ function getRecords () {
return chain(Object.values(require('electron-i18n').docs['en-US']))
.filter(tutorial => !tutorial.isApiDoc && !tutorial.isApiStructureDoc)
.map(tutorial => {
const {title, githubUrl, slug, sections} = tutorial
const { title, githubUrl, slug, sections } = tutorial
const objectID = `tutorial-${slug}`
const html = sections.map(section => section.html).join('\n\n')
const body = cheerio.load(html).text()

Просмотреть файл

@ -1,5 +1,5 @@
const assert = require('assert')
const {chunk, isArray, isString} = require('lodash')
const { chunk, isArray, isString } = require('lodash')
const algoliasearch = require('algoliasearch')
const countArrayValues = require('count-array-values')
@ -18,8 +18,8 @@ module.exports = class AlgoliaIndex {
// each ID is unique
const objectIDs = this.records.map(record => record.objectID)
const dupes = countArrayValues(objectIDs)
.filter(({value, count}) => count > 1)
.map(({value}) => value)
.filter(({ value, count }) => count > 1)
.map(({ value }) => value)
assert(!dupes.length, `every objectID must be unique. dupes: ${dupes.join('; ')}`)
this.records.forEach(record => {
@ -37,11 +37,12 @@ module.exports = class AlgoliaIndex {
return true
}
upload () {
async upload () {
this.validate()
const {ALGOLIA_APPLICATION_ID, ALGOLIA_API_KEY} = process.env
const { ALGOLIA_APPLICATION_ID, ALGOLIA_API_KEY } = process.env
const client = algoliasearch(ALGOLIA_APPLICATION_ID, ALGOLIA_API_KEY)
await client.deleteIndex(this.name)
const index = client.initIndex(this.name)
const chunks = chunk(this.records, 1000)

14542
package-lock.json сгенерированный Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -7,9 +7,9 @@
"license": "MIT",
"main": "index.js",
"scripts": {
"build": "script/build.js",
"build": "node script/build.js",
"preupload": "npm run test",
"upload": "script/upload.js",
"upload": "node script/upload.js",
"update": "script/update.sh",
"pretest": "npm run build",
"test": "tape test.js | tap-spec && standard --fix",

36
test.js
Просмотреть файл

@ -10,7 +10,7 @@ test('electron-search', t => {
// All Indices
// ----------------------------------------------------------------------
const indexNames = ['apis', 'apps', 'packages', 'tutorials']
const indexNames = ['apis', 'apps', 'glossary', 'packages', 'tutorials']
t.deepEqual(Object.keys(indices), indexNames, 'defines expected indexNames as keys')
t.deepEqual(Object.values(indices).map(index => index.name), indexNames, 'has expected index names')
@ -40,7 +40,7 @@ test('electron-search', t => {
})
const apisWithTldrs = apis.filter(api => api.tldr && api.tldr.length > 10)
const tldrThreshold = 95
const tldrThreshold = 80
t.ok(apisWithTldrs.length / apis.length * 100 > tldrThreshold, `At least ${tldrThreshold}% of APIs have a tldr`)
// method URLs should match the slugs generated by github.com (and hubdown)
@ -64,6 +64,21 @@ test('electron-search', t => {
t.ok(tutorial.keyValuePairs.includes('is:tutorial'), `${tutorial.title} has is:tutorial key-value pair`)
})
// Glossary
// ----------------------------------------------------------------------
const glossarys = indices.glossary.records
t.ok(glossarys.length > 15, 'lots of glossary')
glossarys.forEach(glossary => {
if (!glossary.term) console.log(glossary)
t.equal(typeof glossary.term, 'string', `${glossary.title} has a title`)
t.equal(typeof glossary.description, 'string', `${glossary.title} has a body`)
t.ok(isURL(glossary.url), `${glossary.title} has a valid website URL`)
t.ok(glossary.keyValuePairs.includes('is:doc'), `${glossary.title} has is:doc key-value pair`)
t.ok(glossary.keyValuePairs.includes('is:glossary'), `${glossary.title} has is:glossary key-value pair`)
})
// Packages
// ----------------------------------------------------------------------
const packages = indices.packages.records
@ -79,8 +94,23 @@ test('electron-search', t => {
// t.ok(isURL(pkg.repository), `${pkg.title} has a valid repository`)
})
// TODO: Apps
// Apps
// ----------------------------------------------------------------------
const apps = indices.apps.records
t.ok(apps.length > 500, 'lots of APPS')
apps.forEach(app => {
if (!app.name) console.log(app)
t.equal(typeof app.name, 'string', `${app.name} has a name`)
t.ok(app.keyValuePairs.includes('is:app'), `${app.name} has is:pkg key-value pair`)
t.ok(app.keyValuePairs.includes('is:app'), `${app.name} has is:package key-value pair`)
t.equal(typeof app.category, 'string', `${app.name} has category`)
t.equal(typeof app.icon, 'string', `${app.name} has icon`)
// Skipped, not all apps have a website or repository.
// t.ok(isURL(app.website), `${app.title} has a valid website URL`)
// t.ok(isURL(app.repository), `${app.title} has a valid repository`)
})
// TODO: Repos
// ----------------------------------------------------------------------