diff --git a/example/bundle-hub2.css b/example/bundle-hub2.css index 3333516eb..8a0be9155 100644 --- a/example/bundle-hub2.css +++ b/example/bundle-hub2.css @@ -9360,22 +9360,40 @@ body.page-password footer, -ms-animation-duration: 2s; animation-duration: 2s; } +.is-lang-c #hub-reference .hub-api .code-sample .hub-lang-c { + display: block; +} +.is-lang-c #hub-reference .hub-api .code-sample .hub-lang-switch-c { + color: #fff; +} +.is-lang-cplusplus #hub-reference .hub-api .code-sample .hub-lang-cplusplus { + display: block; +} +.is-lang-cplusplus #hub-reference .hub-api .code-sample .hub-lang-switch-cplusplus { + color: #fff; +} +.is-lang-csharp #hub-reference .hub-api .code-sample .hub-lang-csharp { + display: block; +} +.is-lang-csharp #hub-reference .hub-api .code-sample .hub-lang-switch-csharp { + color: #fff; +} .is-lang-curl #hub-reference .hub-api .code-sample .hub-lang-curl { display: block; } .is-lang-curl #hub-reference .hub-api .code-sample .hub-lang-switch-curl { color: #fff; } -.is-lang-node #hub-reference .hub-api .code-sample .hub-lang-node { +.is-lang-go #hub-reference .hub-api .code-sample .hub-lang-go { display: block; } -.is-lang-node #hub-reference .hub-api .code-sample .hub-lang-switch-node { +.is-lang-go #hub-reference .hub-api .code-sample .hub-lang-switch-go { color: #fff; } -.is-lang-ruby #hub-reference .hub-api .code-sample .hub-lang-ruby { +.is-lang-java #hub-reference .hub-api .code-sample .hub-lang-java { display: block; } -.is-lang-ruby #hub-reference .hub-api .code-sample .hub-lang-switch-ruby { +.is-lang-java #hub-reference .hub-api .code-sample .hub-lang-switch-java { color: #fff; } .is-lang-javascript #hub-reference .hub-api .code-sample .hub-lang-javascript { @@ -9384,46 +9402,52 @@ body.page-password footer, .is-lang-javascript #hub-reference .hub-api .code-sample .hub-lang-switch-javascript { color: #fff; } -.is-lang-python #hub-reference .hub-api .code-sample .hub-lang-python { +.is-lang-kotlin #hub-reference .hub-api .code-sample .hub-lang-kotlin { display: block; } -.is-lang-python #hub-reference .hub-api .code-sample .hub-lang-switch-python { +.is-lang-kotlin #hub-reference .hub-api .code-sample .hub-lang-switch-kotlin { color: #fff; } -.is-lang-php #hub-reference .hub-api .code-sample .hub-lang-php { +.is-lang-node #hub-reference .hub-api .code-sample .hub-lang-node { display: block; } -.is-lang-php #hub-reference .hub-api .code-sample .hub-lang-switch-php { +.is-lang-node #hub-reference .hub-api .code-sample .hub-lang-switch-node { color: #fff; } -.is-lang-swift #hub-reference .hub-api .code-sample .hub-lang-swift { +.is-lang-objectivec #hub-reference .hub-api .code-sample .hub-lang-objectivec { display: block; } -.is-lang-swift #hub-reference .hub-api .code-sample .hub-lang-switch-swift { +.is-lang-objectivec #hub-reference .hub-api .code-sample .hub-lang-switch-objectivec { color: #fff; } -.is-lang-objectivec #hub-reference .hub-api .code-sample .hub-lang-objectivec { +.is-lang-php #hub-reference .hub-api .code-sample .hub-lang-php { display: block; } -.is-lang-objectivec #hub-reference .hub-api .code-sample .hub-lang-switch-objectivec { +.is-lang-php #hub-reference .hub-api .code-sample .hub-lang-switch-php { color: #fff; } -.is-lang-csharp #hub-reference .hub-api .code-sample .hub-lang-csharp { +.is-lang-powershell #hub-reference .hub-api .code-sample .hub-lang-powershell { display: block; } -.is-lang-csharp #hub-reference .hub-api .code-sample .hub-lang-switch-csharp { +.is-lang-powershell #hub-reference .hub-api .code-sample .hub-lang-switch-powershell { color: #fff; } -.is-lang-java #hub-reference .hub-api .code-sample .hub-lang-java { +.is-lang-python #hub-reference .hub-api .code-sample .hub-lang-python { display: block; } -.is-lang-java #hub-reference .hub-api .code-sample .hub-lang-switch-java { +.is-lang-python #hub-reference .hub-api .code-sample .hub-lang-switch-python { color: #fff; } -.is-lang-go #hub-reference .hub-api .code-sample .hub-lang-go { +.is-lang-ruby #hub-reference .hub-api .code-sample .hub-lang-ruby { display: block; } -.is-lang-go #hub-reference .hub-api .code-sample .hub-lang-switch-go { +.is-lang-ruby #hub-reference .hub-api .code-sample .hub-lang-switch-ruby { + color: #fff; +} +.is-lang-swift #hub-reference .hub-api .code-sample .hub-lang-swift { + display: block; +} +.is-lang-swift #hub-reference .hub-api .code-sample .hub-lang-switch-swift { color: #fff; } #hub-reference .hub-api .code-sample .docs-right { diff --git a/example/swagger-files/examples.json b/example/swagger-files/examples.json index f4dfc0332..03fc15171 100644 --- a/example/swagger-files/examples.json +++ b/example/swagger-files/examples.json @@ -90,5 +90,21 @@ }, "x-explorer-enabled": true, "x-samples-enabled": true, - "x-samples-languages": ["curl", "node", "ruby", "javascript", "python"] + "x-samples-languages": [ + "c", + "cplusplus", + "csharp", + "curl", + "go", + "java", + "javascript", + "kotlin", + "node", + "objectivec", + "php", + "powershell", + "python", + "ruby", + "swift" + ] } diff --git a/packages/api-explorer/__tests__/lib/generate-code-snippet.test.js b/packages/api-explorer/__tests__/lib/generate-code-snippet.test.js index edccd0825..21be638b2 100644 --- a/packages/api-explorer/__tests__/lib/generate-code-snippet.test.js +++ b/packages/api-explorer/__tests__/lib/generate-code-snippet.test.js @@ -66,10 +66,25 @@ test('should return with unhighlighted code', () => { describe('#getLangName()', () => { it('should convert name to correct case', () => { + expect(getLangName('c')).toBe('C'); + expect(getLangName('cplusplus')).toBe('C++'); + expect(getLangName('csharp')).toBe('C#'); + expect(getLangName('curl')).toBe('cURL'); expect(getLangName('go')).toBe('Go'); + expect(getLangName('java')).toBe('Java'); + expect(getLangName('javascript')).toBe('JavaScript'); + expect(getLangName('kotlin')).toBe('Kotlin'); + expect(getLangName('node')).toBe('Node'); + expect(getLangName('objectivec')).toBe('Objective-C'); + expect(getLangName('php')).toBe('PHP'); + expect(getLangName('powershell')).toBe('PowerShell'); + expect(getLangName('python')).toBe('Python'); + expect(getLangName('ruby')).toBe('Ruby'); + expect(getLangName('swift')).toBe('Swift'); }); it('should pass through unknown values', () => { expect(getLangName('HTTP')).toBe('HTTP'); + expect(getLangName('unknown')).toBe('unknown'); }); }); diff --git a/packages/api-explorer/src/lib/generate-code-snippet.js b/packages/api-explorer/src/lib/generate-code-snippet.js index ee1a66522..cfc05197e 100644 --- a/packages/api-explorer/src/lib/generate-code-snippet.js +++ b/packages/api-explorer/src/lib/generate-code-snippet.js @@ -1,62 +1,68 @@ const HTTPSnippet = require('httpsnippet'); const generateHar = require('./oas-to-har'); const syntaxHighlighter = require('@readme/syntax-highlighter'); +const uppercase = require('@readme/syntax-highlighter/uppercase'); const supportedLanguages = { - node: { - httpsnippet: ['node', 'request'], - highlight: 'javascript', - name: 'Node', + c: { + httpsnippet: ['c'], + highlight: 'text/x-csrc', + }, + cplusplus: { + httpsnippet: ['c'], + highlight: 'text/x-c++src', + }, + csharp: { + httpsnippet: ['csharp', 'restsharp'], + highlight: 'text/x-csharp', }, curl: { httpsnippet: ['shell', 'curl'], highlight: 'shell', - name: 'cURL', }, - ruby: { - httpsnippet: ['ruby'], - highlight: 'ruby', - name: 'Ruby', + go: { + httpsnippet: ['go', 'native'], + highlight: 'go', + }, + java: { + httpsnippet: ['java', 'okhttp'], + highlight: 'java', }, javascript: { httpsnippet: ['javascript', 'xhr', { cors: false }], highlight: 'javascript', - name: 'JavaScript', + }, + kotlin: { + httpsnippet: ['java', 'okhttp'], + highlight: 'java', + }, + node: { + httpsnippet: ['node', 'request'], + highlight: 'javascript', }, objectivec: { httpsnippet: ['objc', 'NSURLSession'], highlight: 'objectivec', - name: 'Objective-C', - }, - python: { - httpsnippet: ['python', 'requests'], - highlight: 'python', - name: 'Python', - }, - java: { - httpsnippet: ['java', 'okhttp'], - highlight: 'java', - name: 'Java', }, php: { httpsnippet: ['php', 'curl'], highlight: 'php', - name: 'PHP', }, - csharp: { - httpsnippet: ['csharp', 'restsharp'], - highlight: 'text/x-csharp', - name: 'C#', + powershell: { + httpsnippet: ['powershell'], + highlight: 'powershell', + }, + python: { + httpsnippet: ['python', 'requests'], + highlight: 'python', + }, + ruby: { + httpsnippet: ['ruby'], + highlight: 'ruby', }, swift: { httpsnippet: ['swift', 'nsurlsession'], highlight: 'swift', - name: 'Swift', - }, - go: { - httpsnippet: ['go', 'native'], - highlight: 'go', - name: 'Go', }, }; @@ -76,8 +82,10 @@ module.exports = (oas, operation, values, auth, lang) => { const code = snippet.convert(...language.httpsnippet); - return { snippet: syntaxHighlighter(code, language.highlight, { dark: true }), code }; + return { + snippet: syntaxHighlighter(code, language.highlight, { dark: true }), + code, + }; }; -module.exports.getLangName = lang => - supportedLanguages[lang] ? supportedLanguages[lang].name : lang; +module.exports.getLangName = lang => (supportedLanguages[lang] ? uppercase(lang) : lang); diff --git a/packages/syntax-highlighter/codemirror.jsx b/packages/syntax-highlighter/codemirror.jsx index 7811d0fa1..8e3b9d6a9 100644 --- a/packages/syntax-highlighter/codemirror.jsx +++ b/packages/syntax-highlighter/codemirror.jsx @@ -8,14 +8,16 @@ const { VARIABLE_REGEXP } = Variable; require('codemirror/addon/runmode/runmode'); require('codemirror/mode/meta.js'); -require('codemirror/mode/shell/shell'); -require('codemirror/mode/javascript/javascript'); -require('codemirror/mode/ruby/ruby'); -require('codemirror/mode/python/python'); require('codemirror/mode/clike/clike'); +require('codemirror/mode/dockerfile/dockerfile'); +require('codemirror/mode/go/go'); require('codemirror/mode/htmlmixed/htmlmixed'); +require('codemirror/mode/javascript/javascript'); require('codemirror/mode/php/php'); -require('codemirror/mode/go/go'); +require('codemirror/mode/powershell/powershell'); +require('codemirror/mode/python/python'); +require('codemirror/mode/ruby/ruby'); +require('codemirror/mode/shell/shell'); require('codemirror/mode/swift/swift'); function getMode(lang) { diff --git a/packages/syntax-highlighter/modes.js b/packages/syntax-highlighter/modes.js index ea8d5a64c..e9bf3c98b 100644 --- a/packages/syntax-highlighter/modes.js +++ b/packages/syntax-highlighter/modes.js @@ -10,26 +10,26 @@ // We also have the mimeType to potentially in future load // in new types dynamically module.exports = { - html: 'htmlmixed', - json: ['javascript', 'application/ld+json'], - text: ['null', 'text/plain'], - markdown: 'gfm', - stylus: 'scss', - bash: 'shell', - mysql: 'sql', - sql: ['sql', 'text/x-sql'], - curl: 'shell', asp: 'clike', - csharp: ['clike', 'text/x-csharp'], - cplusplus: ['clike', 'text/x-c++src'], + bash: 'shell', c: 'clike', + cplusplus: ['clike', 'text/x-c++src'], + csharp: ['clike', 'text/x-csharp'], + curl: 'shell', + go: ['go', 'text/x-go'], + html: 'htmlmixed', java: ['clike', 'text/x-java'], - scala: ['clike', 'text/x-scala'], - objectivec: ['clike', 'text/x-objectivec'], + json: ['javascript', 'application/ld+json'], kotlin: ['clike', 'text/x-kotlin'], - typescript: ['javascript', 'text/typescript'], liquid: 'htmlmixed', - scss: 'css', + markdown: 'gfm', + mysql: 'sql', + objectivec: ['clike', 'text/x-objectivec'], php: ['php', 'text/x-php'], - go: ['go', 'text/x-go'], + scala: ['clike', 'text/x-scala'], + scss: 'css', + sql: ['sql', 'text/x-sql'], + stylus: 'scss', + text: ['null', 'text/plain'], + typescript: ['javascript', 'text/typescript'], }; diff --git a/packages/syntax-highlighter/package-lock.json b/packages/syntax-highlighter/package-lock.json index a5f4a342b..ce011d5c1 100644 --- a/packages/syntax-highlighter/package-lock.json +++ b/packages/syntax-highlighter/package-lock.json @@ -1,6 +1,6 @@ { "name": "@readme/syntax-highlighter", - "version": "4.5.2", + "version": "4.6.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1388,9 +1388,9 @@ "dev": true }, "codemirror": { - "version": "5.31.0", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.31.0.tgz", - "integrity": "sha512-LKbMZKoAz7pMmWuSEl253G6yyloSulj1kXfvYv+3n3I8wMiI7QwnCHwKM3Zw5S9ItNV28Layq0/ihQXWmn9T9w==" + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.48.2.tgz", + "integrity": "sha512-i9VsmC8AfA5ji6EDIZ+aoSe4vt9FcwPLdHB1k1ItFbVyuOFRrcfvnoKqwZlC7EVA2UmTRiNEypE4Uo7YvzVY8Q==" }, "collection-visit": { "version": "1.0.0", @@ -2590,7 +2590,7 @@ }, "debug": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "resolved": false, "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "optional": true, diff --git a/packages/syntax-highlighter/package.json b/packages/syntax-highlighter/package.json index de68cea6b..92d2b8b39 100644 --- a/packages/syntax-highlighter/package.json +++ b/packages/syntax-highlighter/package.json @@ -4,12 +4,13 @@ "version": "4.6.0", "dependencies": { "@readme/variable": "^4.3.2", - "codemirror": "^5.31.0", + "codemirror": "^5.48.2", "react": "^16.4.2" }, "scripts": { "lint": "eslint -f unix . --ext .jsx --ext .js", "inspect": "jsinspect", + "prettier:write": "prettier --write \"./**/**.{js,jsx}\"", "prettier": "prettier --list-different \"./**/**.{js,jsx}\"", "pretest": "npm run lint && npm run inspect && npm run prettier", "test": "jest --coverage --runInBand" diff --git a/packages/syntax-highlighter/test/index.test.js b/packages/syntax-highlighter/test/index.test.js index 916cabaf2..b2b4b9d9b 100644 --- a/packages/syntax-highlighter/test/index.test.js +++ b/packages/syntax-highlighter/test/index.test.js @@ -60,38 +60,56 @@ test('should keep enclosing characters around the variable', () => { ).toEqual("'APIKEY'"); }); -test('should work for modes with an array like java', () => { - expect(shallow(syntaxHighlighter('service = client.service().messaging();', 'java')).html()).toBe( - 'service = client.service().messaging();', - ); -}); - -test('should work for html', () => { - expect(shallow(syntaxHighlighter('
test
', 'html')).html()).toBe( - '<p>test</p>', - ); -}); - -test('should work for php without opening tag', () => { - expect(shallow(syntaxHighlighter('echo "Hello World";', 'php')).html()).toContain('cm-keyword'); -}); - -test('should work for kotlin', () => { - expect(shallow(syntaxHighlighter('println("$index: $element")', 'kotlin')).html()).toContain( - 'cm-variable', - ); -}); - -test('should work for go', () => { - expect(shallow(syntaxHighlighter('func main() {}', 'go')).html()).toContain('cm-variable'); -}); - -test('should work for typescript', () => { - expect( - shallow(syntaxHighlighter('let { a, b }: { a: string, b: number } = o;', 'typescript')).html(), - ).toContain('cm-variable'); -}); - -test('should work for swift', () => { - expect(shallow(syntaxHighlighter('var x = 0;', 'swift')).html()).toContain('cm-def'); +describe('specific languages', () => { + test('should work for modes with an array like java', () => { + expect( + shallow(syntaxHighlighter('service = client.service().messaging();', 'java')).html(), + ).toBe( + 'service = client.service().messaging();', + ); + }); + + test('should work for html', () => { + expect(shallow(syntaxHighlighter('test
', 'html')).html()).toBe( + '<p>test</p>', + ); + }); + + test('should work for php without opening tag', () => { + expect(shallow(syntaxHighlighter('echo "Hello World";', 'php')).html()).toContain('cm-keyword'); + }); + + test('should work for dockerfiles', () => { + expect(shallow(syntaxHighlighter('FROM alpine:3.4', 'dockerfile')).html()).toContain( + 'cm-keyword', + ); + }); + + test('should work for kotlin', () => { + expect(shallow(syntaxHighlighter('println("$index: $element")', 'kotlin')).html()).toContain( + 'cm-variable', + ); + }); + + test('should work for go', () => { + expect(shallow(syntaxHighlighter('func main() {}', 'go')).html()).toContain('cm-variable'); + }); + + test('should work for powershell', () => { + expect( + shallow(syntaxHighlighter('$headers.Add("accept", "application/json")', 'powershell')).html(), + ).toContain('cm-variable'); + }); + + test('should work for typescript', () => { + expect( + shallow( + syntaxHighlighter('let { a, b }: { a: string, b: number } = o;', 'typescript'), + ).html(), + ).toContain('cm-variable'); + }); + + test('should work for swift', () => { + expect(shallow(syntaxHighlighter('var x = 0;', 'swift')).html()).toContain('cm-def'); + }); }); diff --git a/packages/syntax-highlighter/test/uppercase.test.js b/packages/syntax-highlighter/test/uppercase.test.js index dfd2ba1db..10a07f251 100644 --- a/packages/syntax-highlighter/test/uppercase.test.js +++ b/packages/syntax-highlighter/test/uppercase.test.js @@ -2,6 +2,8 @@ const { uppercase } = require('../'); test('should uppercase known languages', () => { expect(uppercase('http')).toBe('HTTP'); + expect(uppercase('kotlin')).toBe('Kotlin'); + expect(uppercase('powershell')).toBe('PowerShell'); }); test('should pass through unknown languages', () => { diff --git a/packages/syntax-highlighter/uppercase.js b/packages/syntax-highlighter/uppercase.js index 2919f44c2..f418cfbdf 100644 --- a/packages/syntax-highlighter/uppercase.js +++ b/packages/syntax-highlighter/uppercase.js @@ -23,15 +23,18 @@ const codeTypes = { jinja2: 'Jinja2', json: 'JSON', julia: 'Julia', + kotlin: 'Kotlin', less: 'LESS', liquid: 'Liquid', lua: 'Lua', markdown: 'Markdown', mysql: 'MySQL', + node: 'Node', objectivec: 'Objective-C', perl: 'Perl', php: 'PHP', pgsql: 'Postgres', + powershell: 'PowerShell', python: 'Python', r: 'R', ruby: 'Ruby', diff --git a/packages/variable/package-lock.json b/packages/variable/package-lock.json index 2810a0fe2..68507f159 100644 --- a/packages/variable/package-lock.json +++ b/packages/variable/package-lock.json @@ -1,6 +1,6 @@ { "name": "@readme/variable", - "version": "4.3.1", + "version": "4.3.2", "lockfileVersion": 1, "requires": true, "dependencies": {