diff --git a/CHANGES.md b/CHANGES.md index a5ba4a83d8..f42f4d4304 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -18,6 +18,7 @@ Core Grammars: - enh(lua) add 'pluto' as an alias [Sainan] - enh(bash) add reserved keywords `time` and `coproc` [Álvaro Mondéjar][] - fix(c) - Fixed hex numbers with decimals [Dxuian] +- fix(typescript) - Fixedoptional property not highlighted correctly [Dxuian] - fix(ruby) - fix `|=` operator false positives (as block arguments) [Aboobacker MK] New Grammars: diff --git a/src/languages/javascript.js b/src/languages/javascript.js index 9cad8c9641..313246c55b 100644 --- a/src/languages/javascript.js +++ b/src/languages/javascript.js @@ -265,7 +265,7 @@ export default function(hljs) { const PARAMS = { className: 'params', // convert this to negative lookbehind in v12 - begin: /(\s*)\(/, // to match the parms with + begin: /(\s*)\(/, // to match the parms with end: /\)/, excludeBegin: true, excludeEnd: true, @@ -476,8 +476,8 @@ export default function(hljs) { NUMBER, CLASS_REFERENCE, { - className: 'attr', - begin: IDENT_RE + regex.lookahead(':'), + scope: 'attr', + match: IDENT_RE + regex.lookahead(':'), relevance: 0 }, FUNCTION_VARIABLE, diff --git a/src/languages/typescript.js b/src/languages/typescript.js index 37a46ad34f..beeca2a820 100644 --- a/src/languages/typescript.js +++ b/src/languages/typescript.js @@ -12,6 +12,7 @@ import javascript from "./javascript.js"; /** @type LanguageFn */ export default function(hljs) { + const regex = hljs.regex; const tsLanguage = javascript(hljs); const IDENT_RE = ECMAScript.IDENT_RE; @@ -68,13 +69,11 @@ export default function(hljs) { "override", "satisfies" ]; - /* namespace is a TS keyword but it's fine to use it as a variable name too. const message = 'foo'; const namespace = 'bar'; */ - const KEYWORDS = { $pattern: ECMAScript.IDENT_RE, keyword: ECMAScript.KEYWORDS.concat(TS_SPECIFIC_KEYWORDS), @@ -82,6 +81,7 @@ export default function(hljs) { built_in: ECMAScript.BUILT_INS.concat(TYPES), "variable.language": ECMAScript.BUILT_IN_VARIABLES }; + const DECORATOR = { className: 'meta', begin: '@' + IDENT_RE, @@ -102,15 +102,25 @@ export default function(hljs) { tsLanguage.exports.PARAMS_CONTAINS.push(DECORATOR); // highlight the function params - const ATTRIBUTE_HIGHLIGHT = tsLanguage.contains.find(c => c.className === "attr"); + const ATTRIBUTE_HIGHLIGHT = tsLanguage.contains.find(c => c.scope === "attr"); + + // take default attr rule and extend it to support optionals + const OPTIONAL_KEY_OR_ARGUMENT = Object.assign({}, + ATTRIBUTE_HIGHLIGHT, + { match: regex.concat(IDENT_RE, regex.lookahead(/\s*\?:/)) } + ); tsLanguage.exports.PARAMS_CONTAINS.push([ tsLanguage.exports.CLASS_REFERENCE, // class reference for highlighting the params types ATTRIBUTE_HIGHLIGHT, // highlight the params key + OPTIONAL_KEY_OR_ARGUMENT, // Added for optional property assignment highlighting ]); + + // Add the optional property assignment highlighting for objects or classes tsLanguage.contains = tsLanguage.contains.concat([ DECORATOR, NAMESPACE, INTERFACE, + OPTIONAL_KEY_OR_ARGUMENT, // Added for optional property assignment highlighting ]); // TS gets a simpler shebang rule than JS diff --git a/test/markup/typescript/generics.expect.txt b/test/markup/typescript/generics.expect.txt index 8b7705bff6..f20a7bb2dd 100644 --- a/test/markup/typescript/generics.expect.txt +++ b/test/markup/typescript/generics.expect.txt @@ -1,10 +1,69 @@ -import { useWeb3React as useWeb3React_ } from '@web3-react/core' - -export const useWeb3React: <T = any>(key?: string) => Modify< +// Updated function with both optional and non-optional parameters +export const useWeb3React: <T = any>(key?: string, version: number) => Modify< ReturnType<typeof useWeb3React_<T>>, - { chainId: SupportedChainIds } + { chainId: SupportedChainIds, network: string } > = useWeb3React_ as any declare global { type SupportedChainIds = 1 | 4 } + +// Optional and non-optional properties in an object type +type Options = { + srcdir: string, + outdir: string, + minify?: boolean, + sourcemap: boolean +} + +// Function with both optional and non-optional parameters +function multiply(a: number, b: number, c?: number, d: number): number { + return a * b * d; +} + +// Optional Function Parameters +function greet(name?: string, age?: number, city: string) { + console.log(`Hello, ${name ?? "Guest"} from ${city}!`); +} + +// Optional and non-optional properties in an interface +interface Person { + name: string; + age?: number; + address?: string; + occupation: string; +} + +// Optional Class Members and Constructor Parameters +class Car { + make: string; + model?: string; + year: number; + + constructor(make: string, year: number, model?: string) { + this.make = make; + this.year = year; + this.model = model; + } +} + + +// Optional Constructor Parameters +class User { + name: string; + age?: number; + city: string; + + constructor(name: string, city: string, age?: number) { + this.name = name; + this.city = city; + this.age = age; + } +} + +// Optional in Function Type Signatures +type PrintMessage = (message: string, sender?: string, timestamp: number) => void; + +const print: PrintMessage = (message, sender, timestamp) => { + console.log(`Message: ${message}, from: ${sender ?? "Anonymous"} at ${timestamp}`); +}; diff --git a/test/markup/typescript/generics.txt b/test/markup/typescript/generics.txt index 218c5f0ddc..8716f613a8 100644 --- a/test/markup/typescript/generics.txt +++ b/test/markup/typescript/generics.txt @@ -1,10 +1,70 @@ -import { useWeb3React as useWeb3React_ } from '@web3-react/core' - -export const useWeb3React: (key?: string) => Modify< +// Updated function with both optional and non-optional parameters +export const useWeb3React: (key?: string, version: number) => Modify< ReturnType>, - { chainId: SupportedChainIds } + { chainId: SupportedChainIds, network: string } > = useWeb3React_ as any declare global { type SupportedChainIds = 1 | 4 } + +// Optional and non-optional properties in an object type +type Options = { + srcdir: string, + outdir: string, + minify?: boolean, + sourcemap: boolean +} + +// Function with both optional and non-optional parameters +function multiply(a: number, b: number, c?: number, d: number): number { + return a * b * d; +} + +// Optional Function Parameters +function greet(name?: string, age?: number, city: string) { + console.log(`Hello, ${name ?? "Guest"} from ${city}!`); +} + +// Optional and non-optional properties in an interface +interface Person { + name: string; + age?: number; + address?: string; + occupation: string; +} + +// Optional Class Members and Constructor Parameters +class Car { + make: string; + model?: string; + year: number; + + constructor(make: string, year: number, model?: string) { + this.make = make; + this.year = year; + this.model = model; + } +} + + +// Optional Constructor Parameters +class User { + name: string; + age?: number; + city: string; + + constructor(name: string, city: string, age?: number) { + this.name = name; + this.city = city; + this.age = age; + } +} + +// Optional in Function Type Signatures +type PrintMessage = (message: string, sender?: string, timestamp: number) => void; + +const print: PrintMessage = (message, sender, timestamp) => { + console.log(`Message: ${message}, from: ${sender ?? "Anonymous"} at ${timestamp}`); +}; +