From ffabdfeed5f85df812efbebf4070bf6936c84988 Mon Sep 17 00:00:00 2001 From: panstromek Date: Sat, 27 Jul 2019 13:08:00 +0200 Subject: [PATCH 1/9] [wip] generate web-types (helper file for WebStorm and related IDEs) - initil work --- ui/build/build.utils.js | 10 ++- ui/build/build.vetur.js | 12 +-- ui/build/build.web-types.js | 113 ++++++++++++++++++++++++++++ ui/build/script.build.javascript.js | 1 + 4 files changed, 125 insertions(+), 11 deletions(-) create mode 100644 ui/build/build.web-types.js diff --git a/ui/build/build.utils.js b/ui/build/build.utils.js index 26e971822ce..326e8406183 100644 --- a/ui/build/build.utils.js +++ b/ui/build/build.utils.js @@ -2,7 +2,8 @@ const fs = require('fs'), path = require('path'), zlib = require('zlib'), - { green, blue, red, cyan } = require('chalk') + { green, blue, red, cyan } = require('chalk'), + kebabRegex = /[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g function getSize (code) { return (code.length / 1024).toFixed(2) + 'kb' @@ -64,3 +65,10 @@ module.exports.rollupQuasarUMD = function (config = {}) { } } } + +module.exports.kebabCase = function (str) { + return str.replace( + kebabRegex, + match => '-' + match.toLowerCase() + ).substring(1) +} diff --git a/ui/build/build.vetur.js b/ui/build/build.vetur.js index a603a2b7e78..eacdd862199 100644 --- a/ui/build/build.vetur.js +++ b/ui/build/build.vetur.js @@ -2,16 +2,8 @@ const path = require('path') const - { logError, writeFile } = require('./build.utils'), - resolve = file => path.resolve(__dirname, '../dist/vetur', file), - kebabRegex = /[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g - -function kebabCase (str) { - return str.replace( - kebabRegex, - match => '-' + match.toLowerCase() - ).substring(1) -} + { logError, writeFile, kebabCase } = require('./build.utils'), + resolve = file => path.resolve(__dirname, '../dist/vetur', file) function getTags (data) { const tags = {} diff --git a/ui/build/build.web-types.js b/ui/build/build.web-types.js new file mode 100644 index 00000000000..ab3e4ddd8b5 --- /dev/null +++ b/ui/build/build.web-types.js @@ -0,0 +1,113 @@ +const + path = require('path'), + fs = require('fs'), + { logError, writeFile, kebabCase } = require('./build.utils') + +function resolveType (type) { + if (Array.isArray(type)) { + return type.map(resolveType) + } + if (['Any', 'String', 'Boolean', 'Number'].includes(type)) { + return type.toLowerCase() + } + if (type === 'Array') { + return 'any[]' + } + return type +} + +module.exports.generate = function (data) { + try { + const webtypes = JSON.stringify({ + $schema: '../../schema/web-types.schema.json', + framework: 'vue', + name: 'quasar', + version: process.env.VERSION || require('../package.json').version, + contributions: { + html: { + 'types-syntax': 'typescript', + tags: data.components.map(({ api: { events, props, scopedSlots, slots }, name }) => { + let result = { + name, + // TODO source file can be wrong - this is just a guess for now + 'source-file': `./quasar/src/components/${kebabCase(name.substr(1))}/${name}.js`, + attributes: props && Object.entries(props).map(([name, propApi]) => { + let result = { + name, + type: resolveType(propApi.type), + description: propApi.desc, + 'doc-url': 'https://quasar.dev' + } + if (propApi.required) { + result.required = true + } + if (propApi.default) { + result.default = JSON.stringify(propApi.default) + } + return result + }), + events: events && Object.entries(events).map(([name, eventApi]) => ({ + name, + arguments: eventApi.params && Object.entries(eventApi.params).map(([paramName, paramApi]) => ({ + name: paramName, + type: resolveType(paramApi.type), + description: paramApi.desc, + 'doc-url': 'https://quasar.dev' + })), + description: eventApi.desc, + 'doc-url': 'https://quasar.dev' + })), + slots: slots && Object.entries(slots).map(([name, slotApi]) => ({ + name, + description: slotApi.desc, + 'doc-url': 'https://quasar.dev' + })), + 'vue-scoped-slots': scopedSlots && Object.entries(scopedSlots).map(([name, slotApi]) => ({ + name, + properties: slotApi.scope && Object.entries(slotApi.scope).map(([name, api]) => ({ + name, + type: resolveType(api.type), + description: api.desc, + 'doc-url': 'https://quasar.dev' + })), + description: slotApi.desc, + 'doc-url': 'https://quasar.dev' + })), + description: `${name} - Quasar component`, + 'doc-url': 'https://quasar.dev' + } + if (props && props.value && ((events && events.input) || props.value.category === 'model')) { + result['vue-model'] = { + prop: 'value', + event: 'input' + } + } + return Object.fromEntries(Object.entries(result).filter(([_, v]) => v)) + }), + attributes: data.directives.map(directiveApi => { + return { + name: 'v-' + kebabCase(directiveApi.name), + 'source-file': `./node_modules/quasar/src/directives/${directiveApi.name}.js`, + type: resolveType(directiveApi.api.value.type), + description: `${directiveApi.name} - Quasar directive`, + 'doc-url': 'https://quasar.dev' + } + }) + } + } + }, null, 2) + let webTypesPath = path.resolve(__dirname, '../dist/web-types') + + if (!fs.existsSync(webTypesPath)) { + fs.mkdirSync(webTypesPath) + } + writeFile(path.resolve(webTypesPath, 'web-types.json'), webtypes) + } + catch (err) { + logError(`build.web-types.js: something went wrong...`) + console.log() + console.error(err) + console.log() + process.exit(1) + } +} diff --git a/ui/build/script.build.javascript.js b/ui/build/script.build.javascript.js index ffe9631d448..a8838894b35 100644 --- a/ui/build/script.build.javascript.js +++ b/ui/build/script.build.javascript.js @@ -95,6 +95,7 @@ require('./build.api').generate() require('./build.vetur').generate(data) require('./build.lang-index').generate() require('./build.types').generate(data) + require('./build.web-types').generate(data) }) /** From 8fc67aece739d862384d57cae39a66fdd052f321 Mon Sep 17 00:00:00 2001 From: panstromek Date: Wed, 31 Jul 2019 19:42:55 +0200 Subject: [PATCH 2/9] add web types into package.json --- ui/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/package.json b/ui/package.json index b6197097225..3671e05667b 100644 --- a/ui/package.json +++ b/ui/package.json @@ -106,6 +106,7 @@ "tags": "dist/vetur/quasar-tags.json", "attributes": "dist/vetur/quasar-attributes.json" }, + "web-types": "dist/web-types/web-types.json", "engines": { "node": ">= 8.9.0", "npm": ">= 5.6.0", From 194a3c9e53881698f71f7a7c1ca31c1ff5b15722 Mon Sep 17 00:00:00 2001 From: panstromek Date: Wed, 31 Jul 2019 19:43:17 +0200 Subject: [PATCH 3/9] remove schema (it's not yet published) --- ui/build/build.web-types.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/build/build.web-types.js b/ui/build/build.web-types.js index ab3e4ddd8b5..d08b89e3c6f 100644 --- a/ui/build/build.web-types.js +++ b/ui/build/build.web-types.js @@ -19,7 +19,7 @@ function resolveType (type) { module.exports.generate = function (data) { try { const webtypes = JSON.stringify({ - $schema: '../../schema/web-types.schema.json', + $schema: '', framework: 'vue', name: 'quasar', version: process.env.VERSION || require('../package.json').version, From df014eb527f9e08199c89d23b23fc991db6db41f Mon Sep 17 00:00:00 2001 From: panstromek Date: Wed, 31 Jul 2019 20:10:48 +0200 Subject: [PATCH 4/9] fix paths --- ui/build/build.web-types.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/build/build.web-types.js b/ui/build/build.web-types.js index d08b89e3c6f..e536996d2d6 100644 --- a/ui/build/build.web-types.js +++ b/ui/build/build.web-types.js @@ -30,7 +30,7 @@ module.exports.generate = function (data) { let result = { name, // TODO source file can be wrong - this is just a guess for now - 'source-file': `./quasar/src/components/${kebabCase(name.substr(1))}/${name}.js`, + 'source-file': `./src/components/${kebabCase(name.substr(1))}/${name}.js`, attributes: props && Object.entries(props).map(([name, propApi]) => { let result = { name, @@ -87,7 +87,7 @@ module.exports.generate = function (data) { attributes: data.directives.map(directiveApi => { return { name: 'v-' + kebabCase(directiveApi.name), - 'source-file': `./node_modules/quasar/src/directives/${directiveApi.name}.js`, + 'source-file': `./src/directives/${directiveApi.name}.js`, type: resolveType(directiveApi.api.value.type), description: `${directiveApi.name} - Quasar directive`, 'doc-url': 'https://quasar.dev' From 42e62f8007f260f3e7320792260d047c0f7cc996 Mon Sep 17 00:00:00 2001 From: panstromek Date: Sun, 18 Aug 2019 15:47:31 +0200 Subject: [PATCH 5/9] update to latest web-types spec --- ui/build/build.web-types.js | 57 ++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/ui/build/build.web-types.js b/ui/build/build.web-types.js index e536996d2d6..8f0796947d7 100644 --- a/ui/build/build.web-types.js +++ b/ui/build/build.web-types.js @@ -4,8 +4,9 @@ const { logError, writeFile, kebabCase } = require('./build.utils') function resolveType (type) { + // TODO transform "values" and arrays of values if (Array.isArray(type)) { - return type.map(resolveType) + return type.map(resolveType).join('|') } if (['Any', 'String', 'Boolean', 'Number'].includes(type)) { return type.toLowerCase() @@ -16,6 +17,7 @@ function resolveType (type) { return type } +// TODO add examples to descriptions module.exports.generate = function (data) { try { const webtypes = JSON.stringify({ @@ -29,12 +31,17 @@ module.exports.generate = function (data) { tags: data.components.map(({ api: { events, props, scopedSlots, slots }, name }) => { let result = { name, - // TODO source file can be wrong - this is just a guess for now - 'source-file': `./src/components/${kebabCase(name.substr(1))}/${name}.js`, + source: { + module: 'quasar', + symbol: name + }, attributes: props && Object.entries(props).map(([name, propApi]) => { let result = { name, - type: resolveType(propApi.type), + value: { + kind: 'expression', + type: resolveType(propApi.type) + }, description: propApi.desc, 'doc-url': 'https://quasar.dev' } @@ -44,6 +51,10 @@ module.exports.generate = function (data) { if (propApi.default) { result.default = JSON.stringify(propApi.default) } + if (propApi.type === 'Boolean') { + // Deprecated but used for compatibility with WebStorm 2019.2. + result.type = 'boolean' + } return result }), events: events && Object.entries(events).map(([name, eventApi]) => ({ @@ -82,16 +93,40 @@ module.exports.generate = function (data) { event: 'input' } } - return Object.fromEntries(Object.entries(result).filter(([_, v]) => v)) + Object.entries(result).forEach(([key, v]) => { + if (!v) { + delete result[key] + } + }) + + return result }), - attributes: data.directives.map(directiveApi => { - return { - name: 'v-' + kebabCase(directiveApi.name), - 'source-file': `./src/directives/${directiveApi.name}.js`, - type: resolveType(directiveApi.api.value.type), - description: `${directiveApi.name} - Quasar directive`, + attributes: data.directives.map(({ name, api: { modifiers, value } }) => { + let valueType = value.type + let result = { + name: 'v-' + kebabCase(name), + source: { + module: 'quasar', + symbol: name + }, + required: false, // Directive is never required + description: `${name} - Quasar directive`, 'doc-url': 'https://quasar.dev' } + if (modifiers) { + result['vue-modifiers'] = Object.entries(modifiers).map(([name, api]) => ({ + name, + description: api.desc, + 'doc-url': 'https://quasar.dev' + })) + } + if (valueType !== 'Boolean') { + result.value = { + kind: 'expression', + type: resolveType(value.type) + } + } + return result }) } } From 8d95c9f0272b94529653737ac41ab25d644d19a6 Mon Sep 17 00:00:00 2001 From: panstromek Date: Sun, 18 Aug 2019 16:14:48 +0200 Subject: [PATCH 6/9] include object to type resolving --- ui/build/build.web-types.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ui/build/build.web-types.js b/ui/build/build.web-types.js index 8f0796947d7..b07fd4c9fa2 100644 --- a/ui/build/build.web-types.js +++ b/ui/build/build.web-types.js @@ -4,11 +4,11 @@ const { logError, writeFile, kebabCase } = require('./build.utils') function resolveType (type) { - // TODO transform "values" and arrays of values + // TODO transform Object with "values" and arrays Objects with values if (Array.isArray(type)) { return type.map(resolveType).join('|') } - if (['Any', 'String', 'Boolean', 'Number'].includes(type)) { + if (['Any', 'String', 'Boolean', 'Number', 'Object'].includes(type)) { return type.toLowerCase() } if (type === 'Array') { @@ -137,8 +137,7 @@ module.exports.generate = function (data) { fs.mkdirSync(webTypesPath) } writeFile(path.resolve(webTypesPath, 'web-types.json'), webtypes) - } - catch (err) { + } catch (err) { logError(`build.web-types.js: something went wrong...`) console.log() console.error(err) From 5ac6c63f6335711e67c082a7b3b6a6b5103be38d Mon Sep 17 00:00:00 2001 From: panstromek Date: Sun, 18 Aug 2019 17:37:44 +0200 Subject: [PATCH 7/9] add examples to description --- ui/build/build.web-types.js | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/ui/build/build.web-types.js b/ui/build/build.web-types.js index b07fd4c9fa2..e5e682ed4af 100644 --- a/ui/build/build.web-types.js +++ b/ui/build/build.web-types.js @@ -17,7 +17,12 @@ function resolveType (type) { return type } -// TODO add examples to descriptions +function getDescription (propApi) { + return propApi.examples + ? propApi.desc + '\n\nExamples:\n' + propApi.examples.join('\n') + : propApi.desc +} + module.exports.generate = function (data) { try { const webtypes = JSON.stringify({ @@ -42,7 +47,7 @@ module.exports.generate = function (data) { kind: 'expression', type: resolveType(propApi.type) }, - description: propApi.desc, + description: getDescription(propApi), 'doc-url': 'https://quasar.dev' } if (propApi.required) { @@ -62,15 +67,15 @@ module.exports.generate = function (data) { arguments: eventApi.params && Object.entries(eventApi.params).map(([paramName, paramApi]) => ({ name: paramName, type: resolveType(paramApi.type), - description: paramApi.desc, + description: getDescription(paramApi), 'doc-url': 'https://quasar.dev' })), - description: eventApi.desc, + description: getDescription(eventApi), 'doc-url': 'https://quasar.dev' })), slots: slots && Object.entries(slots).map(([name, slotApi]) => ({ name, - description: slotApi.desc, + description: getDescription(slotApi), 'doc-url': 'https://quasar.dev' })), 'vue-scoped-slots': scopedSlots && Object.entries(scopedSlots).map(([name, slotApi]) => ({ @@ -78,10 +83,10 @@ module.exports.generate = function (data) { properties: slotApi.scope && Object.entries(slotApi.scope).map(([name, api]) => ({ name, type: resolveType(api.type), - description: api.desc, + description: getDescription(api), 'doc-url': 'https://quasar.dev' })), - description: slotApi.desc, + description: getDescription(slotApi), 'doc-url': 'https://quasar.dev' })), description: `${name} - Quasar component`, @@ -116,7 +121,7 @@ module.exports.generate = function (data) { if (modifiers) { result['vue-modifiers'] = Object.entries(modifiers).map(([name, api]) => ({ name, - description: api.desc, + description: getDescription(api), 'doc-url': 'https://quasar.dev' })) } From 95b8e2f759100f4b841ef2f82a58b8a649705f36 Mon Sep 17 00:00:00 2001 From: panstromek Date: Sun, 18 Aug 2019 17:59:32 +0200 Subject: [PATCH 8/9] support string enums --- ui/build/build.web-types.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/ui/build/build.web-types.js b/ui/build/build.web-types.js index e5e682ed4af..d4b06a7c449 100644 --- a/ui/build/build.web-types.js +++ b/ui/build/build.web-types.js @@ -3,10 +3,13 @@ const fs = require('fs'), { logError, writeFile, kebabCase } = require('./build.utils') -function resolveType (type) { +function resolveType ({ type, values }) { // TODO transform Object with "values" and arrays Objects with values if (Array.isArray(type)) { - return type.map(resolveType).join('|') + return type.map(type => resolveType({ type })).join('|') + } + if (type === 'String' && values) { + return values.map(v => v === null ? 'null' : `'${v}'`).join('|') } if (['Any', 'String', 'Boolean', 'Number', 'Object'].includes(type)) { return type.toLowerCase() @@ -45,7 +48,7 @@ module.exports.generate = function (data) { name, value: { kind: 'expression', - type: resolveType(propApi.type) + type: resolveType(propApi) }, description: getDescription(propApi), 'doc-url': 'https://quasar.dev' @@ -66,7 +69,7 @@ module.exports.generate = function (data) { name, arguments: eventApi.params && Object.entries(eventApi.params).map(([paramName, paramApi]) => ({ name: paramName, - type: resolveType(paramApi.type), + type: resolveType(paramApi), description: getDescription(paramApi), 'doc-url': 'https://quasar.dev' })), @@ -82,7 +85,7 @@ module.exports.generate = function (data) { name, properties: slotApi.scope && Object.entries(slotApi.scope).map(([name, api]) => ({ name, - type: resolveType(api.type), + type: resolveType(api), description: getDescription(api), 'doc-url': 'https://quasar.dev' })), @@ -128,7 +131,7 @@ module.exports.generate = function (data) { if (valueType !== 'Boolean') { result.value = { kind: 'expression', - type: resolveType(value.type) + type: resolveType(value) } } return result From 15b30fbd287c4d371713c166eded41a0b242100a Mon Sep 17 00:00:00 2001 From: panstromek Date: Sun, 18 Aug 2019 18:03:42 +0200 Subject: [PATCH 9/9] lint --- ui/build/build.web-types.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/build/build.web-types.js b/ui/build/build.web-types.js index d4b06a7c449..fbd866d8ef5 100644 --- a/ui/build/build.web-types.js +++ b/ui/build/build.web-types.js @@ -145,7 +145,8 @@ module.exports.generate = function (data) { fs.mkdirSync(webTypesPath) } writeFile(path.resolve(webTypesPath, 'web-types.json'), webtypes) - } catch (err) { + } + catch (err) { logError(`build.web-types.js: something went wrong...`) console.log() console.error(err)