@@ -8,6 +8,60 @@ const EDITOR_WORD_MIN_LEN = 2;
88var editorAutocompleteMatches = [ ] ;
99var editorAutocompleteIndex = 0 ;
1010
11+ // Built-in domain keyword dictionary spanning all 12 course tracks:
12+ // API-Testing, Playwright, Robot-Framework, Performance-Testing, DB-Design-SQL,
13+ // CLI-Essentials, Security-Testing, Accessibility-Testing, Visual-Regression-Testing,
14+ // CI-CD-Pipeline, Framework-Design, Data-Structures-Algorithms.
15+ const BUILTIN_KEYWORDS = [
16+ // Playwright & API Methods
17+ 'request' , 'get' , 'post' , 'put' , 'delete' , 'patch' , 'status' , 'json' , 'text' , 'headers' ,
18+ 'extraHTTPHeaders' , 'newContext' , 'dispose' , 'page' , 'goto' , 'locator' , 'getByRole' ,
19+ 'getByText' , 'getByTestId' , 'getByPlaceholder' , 'getByLabel' , 'getByTitle' , 'getByAltText' ,
20+ 'click' , 'fill' , 'type' , 'press' , 'check' , 'uncheck' , 'selectOption' , 'waitForSelector' ,
21+ 'waitForURL' , 'waitForLoadState' , 'screenshot' , 'pdf' ,
22+
23+ // Assertions & Matchers
24+ 'expect' , 'toBe' , 'toEqual' , 'toContain' , 'toHaveProperty' , 'toHaveLength' , 'toBeOK' ,
25+ 'toBeVisible' , 'toHaveText' , 'toContainText' , 'toHaveValue' , 'toBeChecked' , 'toBeDisabled' ,
26+ 'toBeEnabled' , 'toHaveURL' , 'toHaveTitle' , 'toHaveCount' , 'toHaveScreenshot' , 'toBeDefined' ,
27+ 'toBeUndefined' , 'toBeTruthy' , 'toBeFalsy' ,
28+
29+ // Robot Framework Keywords
30+ 'Library' , 'Browser' , 'AppiumLibrary' , 'SeleniumLibrary' , 'Keywords' , 'Variables' ,
31+ 'New Page' , 'Click' , 'Fill Text' , 'Get Text' , 'Should Be Equal' , 'Should Contain' ,
32+ 'Should Be True' , 'Open Browser' , 'Input Text' , 'Click Element' , 'Element Should Be Visible' ,
33+ 'Set Variable' , 'Create List' , 'Create Dictionary' ,
34+
35+ // k6 Performance Testing
36+ 'http' , 'del' , 'group' , 'sleep' , 'options' , 'vus' , 'duration' , 'stages' , 'thresholds' ,
37+ 'Trend' , 'Counter' , 'Gauge' , 'Rate' , 'scenario' ,
38+
39+ // SQL & DB Design
40+ 'SELECT' , 'FROM' , 'WHERE' , 'INSERT' , 'INTO' , 'UPDATE' , 'SET' , 'DELETE' , 'JOIN' , 'INNER' ,
41+ 'LEFT' , 'RIGHT' , 'ON' , 'GROUP' , 'BY' , 'HAVING' , 'ORDER' , 'ASC' , 'DESC' , 'LIMIT' , 'OFFSET' ,
42+ 'COUNT' , 'SUM' , 'AVG' , 'MIN' , 'MAX' , 'PRIMARY' , 'KEY' , 'FOREIGN' , 'UNIQUE' , 'DEFAULT' ,
43+ 'CREATE' , 'TABLE' , 'ALTER' , 'DROP' , 'INDEX' , '1NF' , '2NF' , '3NF' , 'BCNF' ,
44+
45+ // CLI, Git & Unix
46+ 'git' , 'commit' , 'checkout' , 'branch' , 'push' , 'pull' , 'rebase' , 'merge' , 'log' ,
47+ 'diff' , 'clone' , 'init' , 'add' , 'reset' , 'stash' , 'ls' , 'cd' , 'pwd' , 'mkdir' , 'rm' ,
48+ 'cp' , 'mv' , 'cat' , 'grep' , 'find' , 'chmod' , 'chown' , 'curl' , 'ssh' , 'tar' , 'sed' , 'awk' ,
49+
50+ // Security, A11y, Visual & CI/CD
51+ 'XSS' , 'SQLi' , 'CSRF' , 'sanitize' , 'encodeURIComponent' , 'innerHTML' , 'textContent' ,
52+ 'Authorization' , 'Bearer' , 'JWT' , 'hash' , 'salt' , 'bcrypt' , 'cors' , 'rateLimit' ,
53+ 'axe' , 'violations' , 'aria-label' , 'aria-expanded' , 'aria-hidden' , 'role' , 'tabindex' ,
54+ 'alt' , 'focus' , 'blur' , 'heading' , 'button' , 'link' , 'img' , 'contrast' ,
55+ 'maxDiffPixels' , 'maxDiffPixelRatio' , 'threshold' , 'mask' , 'fullPage' , 'clip' ,
56+ 'pull_request' , 'schedule' , 'jobs' , 'runs-on' , 'ubuntu-latest' , 'steps' , 'uses' , 'matrix' ,
57+
58+ // Framework Design & DSA
59+ 'PageObject' , 'BasePage' , 'fixtures' , 'extend' , 'globalSetup' , 'globalTeardown' ,
60+ 'config' , 'reporter' , 'use' , 'storageState' , 'trace' ,
61+ 'BigO' , 'Array' , 'Map' , 'Set' , 'Stack' , 'Queue' , 'LinkedList' , 'BinaryTree' , 'Graph' ,
62+ 'DFS' , 'BFS' , 'binarySearch' , 'quickSort' , 'mergeSort' , 'dynamicProgramming' , 'memo' , 'collision'
63+ ] ;
64+
1165// Word (identifier) touching the caret, e.g. typing "res" inside "const res" -> { start, end, word: "res" }
1266function getCurrentWord ( textarea ) {
1367 const caret = textarea . selectionStart ;
@@ -17,9 +71,10 @@ function getCurrentWord(textarea) {
1771 return { start, end : caret , word : value . slice ( start , caret ) } ;
1872}
1973
20- // Every distinct identifier already typed in the editor (word-based completion, like an IDE's local suggestions)
74+ // Every distinct identifier typed in the editor plus built-in domain keywords
2175function getKnownWords ( text ) {
22- return [ ...new Set ( text . match ( EDITOR_WORD_REGEX ) || [ ] ) ] ;
76+ const localWords = text . match ( EDITOR_WORD_REGEX ) || [ ] ;
77+ return [ ...new Set ( [ ...localWords , ...BUILTIN_KEYWORDS ] ) ] ;
2378}
2479
2580// Recompute autocomplete matches for the word at the caret and show/hide the dropdown accordingly
@@ -36,7 +91,7 @@ function updateEditorAutocomplete() {
3691 const known = getKnownWords ( textarea . value ) ;
3792 editorAutocompleteMatches = known
3893 . filter ( w => w !== word && w . toLowerCase ( ) . startsWith ( word . toLowerCase ( ) ) )
39- . slice ( 0 , 6 ) ;
94+ . slice ( 0 , 8 ) ;
4095
4196 if ( ! editorAutocompleteMatches . length ) {
4297 hideEditorAutocomplete ( ) ;
@@ -55,7 +110,7 @@ function getEditorAutocompleteEl(textarea) {
55110 if ( ! container ) return null ;
56111 el = document . createElement ( 'div' ) ;
57112 el . id = 'editor-autocomplete' ;
58- el . style . cssText = 'display: none; position: absolute; max-height: 160px ; overflow-y: auto; background-color: #0b0f17; border: 1px solid var(--border-color); border-radius: 6px; z-index: 20; font-family: var(--font-mono); font-size: 0.8rem;' ;
113+ el . style . cssText = 'display: none; position: absolute; max-height: 180px ; overflow-y: auto; background-color: #0b0f17; border: 1px solid var(--border-color); border-radius: 6px; z-index: 20; font-family: var(--font-mono); font-size: 0.8rem;' ;
59114 container . appendChild ( el ) ;
60115 }
61116 return el ;
0 commit comments