├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── dependabot.yml ├── .gitignore ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── .vscodeignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── client ├── package-lock.json ├── package.json ├── src │ ├── client.ts │ ├── configuration.ts │ ├── constants.ts │ ├── extension.ts │ ├── interfaces.ts │ ├── js-beautify │ │ ├── CHANGELOG.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── js │ │ │ ├── bin │ │ │ │ ├── css-beautify.js │ │ │ │ ├── html-beautify.js │ │ │ │ └── js-beautify.js │ │ │ ├── config │ │ │ │ └── defaults.json │ │ │ ├── index.js │ │ │ ├── lib │ │ │ │ ├── beautifier.js │ │ │ │ ├── beautifier.js.map │ │ │ │ ├── beautifier.min.js │ │ │ │ ├── beautifier.min.js.map │ │ │ │ ├── beautify-css.js │ │ │ │ ├── beautify-html.js │ │ │ │ ├── beautify.js │ │ │ │ ├── cli.js │ │ │ │ └── unpackers │ │ │ │ │ ├── javascriptobfuscator_unpacker.js │ │ │ │ │ ├── myobfuscate_unpacker.js │ │ │ │ │ ├── p_a_c_k_e_r_unpacker.js │ │ │ │ │ └── urlencode_unpacker.js │ │ │ └── src │ │ │ │ ├── cli.js │ │ │ │ ├── core │ │ │ │ ├── directives.js │ │ │ │ ├── inputscanner.js │ │ │ │ ├── options.js │ │ │ │ ├── output.js │ │ │ │ ├── pattern.js │ │ │ │ ├── templatablepattern.js │ │ │ │ ├── token.js │ │ │ │ ├── tokenizer.js │ │ │ │ ├── tokenstream.js │ │ │ │ └── whitespacepattern.js │ │ │ │ ├── css │ │ │ │ ├── beautifier.js │ │ │ │ ├── index.js │ │ │ │ ├── options.js │ │ │ │ └── tokenizer.js │ │ │ │ ├── html │ │ │ │ ├── beautifier.js │ │ │ │ ├── index.js │ │ │ │ ├── options.js │ │ │ │ └── tokenizer.js │ │ │ │ ├── index.js │ │ │ │ ├── javascript │ │ │ │ ├── acorn.js │ │ │ │ ├── beautifier.js │ │ │ │ ├── index.js │ │ │ │ ├── options.js │ │ │ │ └── tokenizer.js │ │ │ │ └── unpackers │ │ │ │ ├── javascriptobfuscator_unpacker.js │ │ │ │ ├── myobfuscate_unpacker.js │ │ │ │ ├── p_a_c_k_e_r_unpacker.js │ │ │ │ └── urlencode_unpacker.js │ │ └── package.json │ ├── language │ │ ├── beautify.ts │ │ ├── configuration.ts │ │ ├── decoration.ts │ │ ├── documentLink.ts │ │ ├── formatter.ts │ │ └── hover.ts │ └── utils.ts └── tsconfig.json ├── extension-browser.webpack.config.js ├── extension.webpack.config.js ├── images ├── logo.png ├── netbeans-theme-preview.png ├── preview.gif └── settings-preview.png ├── language-configuration.json ├── package-lock.json ├── package.json ├── server ├── package-lock.json ├── package.json ├── src │ ├── browser │ │ ├── htmlServerMain.ts │ │ └── htmlServerWorkerMain.ts │ ├── customData.ts │ ├── htmlServer.ts │ ├── languageModelCache.ts │ ├── modes │ │ ├── cssMode.ts │ │ ├── embeddedSupport.ts │ │ ├── formatting.ts │ │ ├── htmlFolding.ts │ │ ├── htmlMode.ts │ │ ├── javascriptLibs.ts │ │ ├── javascriptMode.ts │ │ ├── javascriptSemanticTokens.ts │ │ ├── languageModes.ts │ │ ├── selectionRanges.ts │ │ └── semanticTokens.ts │ ├── node │ │ ├── htmlServerMain.ts │ │ └── nodeFs.ts │ ├── requests.ts │ ├── test │ │ ├── completions.test.ts │ │ ├── documentContext.test.ts │ │ ├── embedded.test.ts │ │ ├── fixtures │ │ │ ├── expected │ │ │ │ ├── 19813-4spaces.html │ │ │ │ ├── 19813-tab.html │ │ │ │ ├── 19813.html │ │ │ │ └── 21634.html │ │ │ └── inputs │ │ │ │ ├── 19813.html │ │ │ │ └── 21634.html │ │ ├── folding.test.ts │ │ ├── formatting.test.ts │ │ ├── pathCompletionFixtures │ │ │ ├── .foo.js │ │ │ ├── about │ │ │ │ ├── about.css │ │ │ │ ├── about.html │ │ │ │ └── media │ │ │ │ │ └── icon.pic │ │ │ ├── index.html │ │ │ └── src │ │ │ │ ├── feature.js │ │ │ │ └── test.js │ │ ├── rename.test.ts │ │ ├── selectionRanges.test.ts │ │ ├── semanticTokens.test.ts │ │ └── words.test.ts │ └── utils │ │ ├── arrays.ts │ │ ├── documentContext.ts │ │ ├── positions.ts │ │ ├── runner.ts │ │ ├── strings.ts │ │ └── validation.ts └── tsconfig.json ├── snippets └── snippets.json ├── syntaxes └── smarty.tmLanguage.json ├── tsconfig.json └── tslint.json /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | ko_fi: aswinkumar863 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior. 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Screenshots** 20 | If applicable, add screenshots to help explain your problem. 21 | 22 | **Context (please complete the following information):** 23 | - Version [e.g. 1.0.0] 24 | 25 | **Additional context** 26 | Add any other context about the problem here. 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: monthly 7 | time: "23:30" 8 | open-pull-requests-limit: 10 9 | ignore: 10 | - dependency-name: ts-loader 11 | versions: 12 | - 8.1.0 13 | - dependency-name: "@types/node" 14 | versions: 15 | - 14.14.31 16 | - 14.14.33 17 | - dependency-name: webpack 18 | versions: 19 | - 5.24.4 20 | - dependency-name: webpack-cli 21 | versions: 22 | - 4.5.0 23 | - package-ecosystem: npm 24 | directory: "/client" 25 | schedule: 26 | interval: monthly 27 | time: "23:30" 28 | open-pull-requests-limit: 10 29 | target-branch: master 30 | ignore: 31 | - dependency-name: "@types/vscode" 32 | versions: 33 | - 1.55.0 34 | - package-ecosystem: npm 35 | directory: "/server" 36 | schedule: 37 | interval: monthly 38 | time: "23:30" 39 | open-pull-requests-limit: 10 40 | target-branch: master 41 | ignore: 42 | - dependency-name: mocha 43 | versions: 44 | - 8.3.2 45 | - dependency-name: vscode-css-languageservice 46 | versions: 47 | - 5.0.3 48 | - 5.1.0 49 | - dependency-name: vscode-html-languageservice 50 | versions: 51 | - 4.0.1 52 | - 4.0.2 53 | - dependency-name: y18n 54 | versions: 55 | - 4.0.1 56 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .vscode-test -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | { 3 | "version": "0.2.0", 4 | "configurations": [ 5 | { 6 | "type": "extensionHost", 7 | "request": "launch", 8 | "name": "Launch Client", 9 | "runtimeExecutable": "${execPath}", 10 | "args": ["--extensionDevelopmentPath=${workspaceRoot}"], 11 | "outFiles": ["${workspaceRoot}/client/dist/**/*.js"], 12 | "preLaunchTask": { 13 | "type": "npm", 14 | "script": "watch" 15 | } 16 | }, 17 | { 18 | "type": "node", 19 | "request": "attach", 20 | "name": "Attach to Server", 21 | "port": 6009, 22 | "restart": true, 23 | "outFiles": ["${workspaceRoot}/server/dist/**/*.js"] 24 | }, 25 | { 26 | "name": "Language Server E2E Test", 27 | "type": "extensionHost", 28 | "request": "launch", 29 | "runtimeExecutable": "${execPath}", 30 | "args": [ 31 | "--extensionDevelopmentPath=${workspaceRoot}", 32 | "--extensionTestsPath=${workspaceRoot}/client/out/test", 33 | "${workspaceRoot}/client/testFixture" 34 | ], 35 | "outFiles": ["${workspaceRoot}/client/dist/test/**/*.js"] 36 | }, 37 | { 38 | "name": "Run Web Extension in VS Code", 39 | "type": "pwa-extensionHost", 40 | "debugWebWorkerHost": true, 41 | "request": "launch", 42 | "args": [ 43 | "--extensionDevelopmentPath=${workspaceFolder}", 44 | "--extensionDevelopmentKind=web" 45 | ], 46 | "outFiles": ["${workspaceFolder}/client/dist/browser/*.js"], 47 | "preLaunchTask": "npm: watch-web" 48 | } 49 | ], 50 | "compounds": [ 51 | { 52 | "name": "Client + Server", 53 | "configurations": ["Launch Client", "Attach to Server"] 54 | } 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.insertSpaces": false, 3 | "tslint.enable": true, 4 | "typescript.tsc.autoDetect": "off", 5 | "typescript.preferences.quoteStyle": "single" 6 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // See https://go.microsoft.com/fwlink/?LinkId=733558 2 | // for the documentation about the tasks.json format 3 | { 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "watch", 9 | "problemMatcher": [ 10 | "$ts-webpack-watch", 11 | "$tslint-webpack-watch" 12 | ], 13 | "isBackground": true, 14 | "presentation": { 15 | "reveal": "never", 16 | "group": "watchers" 17 | }, 18 | "group": { 19 | "kind": "build", 20 | "isDefault": true 21 | } 22 | }, 23 | { 24 | "type": "npm", 25 | "script": "watch-tests", 26 | "problemMatcher": "$tsc-watch", 27 | "isBackground": true, 28 | "presentation": { 29 | "reveal": "never", 30 | "group": "watchers" 31 | }, 32 | "group": "build" 33 | }, 34 | { 35 | "label": "tasks: watch-tests", 36 | "dependsOn": [ 37 | "npm: watch", 38 | "npm: watch-tests" 39 | ], 40 | "problemMatcher": [] 41 | }, 42 | { 43 | "type": "npm", 44 | "script": "watch-web", 45 | "group": "build", 46 | "isBackground": true, 47 | "problemMatcher": ["$ts-webpack-watch"] 48 | } 49 | ] 50 | } -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .github/** 2 | .vscode/** 3 | .gitignore 4 | .travis.yml 5 | **/*.map 6 | **/*.ts 7 | **/tsconfig.base.json 8 | **/tsconfig.json 9 | **/tslint.json 10 | **/node_modules/** 11 | **/*webpack.config.js 12 | **/package-lock.json 13 | client/src/** 14 | server/src/** -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 2.1.1 (June 22, 2023) 2 | * Readme Fixes 3 | 4 | ## 2.1.0 (January 16, 2023) 5 | * Handle relative paths and shorthand includes (PR #440) 6 | * Updated dependencies & HTML language server 7 | * Fix debugging 8 | 9 | ## 2.0.0 (June 19, 2022) 10 | * Now available for [vscode.dev](https://vscode.dev/) and other web platforms. 11 | * Updated dependencies & HTML language server 12 | * Bug Fixes 13 | 14 | ## 1.10.0 (March 13, 2022) 15 | * Respected editorconfig and file indentation (Issues #193, #338) 16 | * Updated dependencies & HTML language server 17 | * Bug Fixes 18 | 19 | ## 1.9.0 (July 31, 2021) 20 | * Formatting issues #267, #242 21 | * Code folding issue #243 22 | * Updated dependencies & language server 23 | * Minor Bug Fixes 24 | 25 | ## 1.8.0 (December 13, 2020) 26 | * Respect `Wrap Attributes` setting. Read [docs](https://github.com/aswinkumar863/smarty-vscode-support#formatting-settings). 27 | * Code navigation for [`include`](https://www.smarty.net/docsv2/en/language.function.include.tpl) function 28 | * Code folding and indentation fixes 29 | * Updated dependencies & language server 30 | * Bug Fixes 31 | 32 | ## 1.7.0 (August 2, 2020) 33 | * Complete cleanup and refactoring 34 | * Updated dependencies & language server 35 | * More HTML formatting options 36 | * [Variable modifiers](https://www.smarty.net/docs/en/language.modifiers.tpl) snippets 37 | * Bug Fixes 38 | 39 | ## 1.6.0 (May 31, 2020) 40 | * Rewrite language grammer 41 | * Comment toggling for `{{...}}` delimiters 42 | * Improved hover documentation 43 | * Toggle highlight decoration command 44 | * Bug Fixes 45 | 46 | ## 1.5.0 (May 14, 2020) 47 | * Updated HTML Language Server 48 | * Bug Fixes 49 | 50 | ## 1.4.0 (May 10, 2020) 51 | * Added `{{...}}` delimiter support 52 | 53 | ## 1.3.0 (May 3, 2020) 54 | * indentationRules added 55 | * indentation on formatting 56 | 57 | ## 1.2.0 (April 13, 2020) 58 | * bundled with webpack to reduce the size 59 | 60 | ## 1.1.0 (April 11, 2020) 61 | * Language Service for better HTML, CSS and JS support 62 | * Autocomplete for HTML, CSS and JS 63 | * Hover Documentation for HTML, CSS and JS 64 | 65 | ## 1.0.3 (April 4, 2020) 66 | * Performance improvements for highlight decoration 67 | 68 | ## 1.0.2 (March 31, 2020) 69 | * html comments inside literal block 70 | * highlighting decoration disabled inside literal block 71 | 72 | ## 1.0.1 (March 29, 2020) 73 | * formatter dependency fixes and improvements 74 | 75 | ## 1.0.0 (March 28, 2020) 76 | 77 | * Syntax highlighting 78 | * Snippet completion 79 | * Bracket autoclosing 80 | * Bracket autosurrounding 81 | * Hover documentation 82 | * Comment toggling 83 | * Code folding 84 | * Code formatting 85 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at aswinkumar863@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 aswinkumar863 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Smarty Template for Visual Studio Code 2 | 3 | [![Latest Release](https://img.shields.io/visual-studio-marketplace/v/aswinkumar863.smarty-template-support?logo=visual-studio-code&label=Smarty%20Template%20Support)](https://marketplace.visualstudio.com/items?itemName=aswinkumar863.smarty-template-support) 4 | [![Installs](https://img.shields.io/visual-studio-marketplace/i/aswinkumar863.smarty-template-support)](https://marketplace.visualstudio.com/items?itemName=aswinkumar863.smarty-template-support) 5 | [![Rating](https://img.shields.io/visual-studio-marketplace/r/aswinkumar863.smarty-template-support)](https://marketplace.visualstudio.com/items?itemName=aswinkumar863.smarty-template-support&ssr=false#review-details) 6 | [![GitHub Stars](https://img.shields.io/github/stars/aswinkumar863/smarty-vscode-support?logo=github)](https://github.com/aswinkumar863/smarty-vscode-support) 7 | [![GitHub closed issues](https://img.shields.io/github/issues-closed/aswinkumar863/smarty-vscode-support)](https://github.com/aswinkumar863/smarty-vscode-support/issues) 8 | 9 | This extension provides [Smarty Template](https://www.smarty.net/) support for Visual Studio Code. 10 | Supports `{...}` and `{{...}}` delimiters. Available for both VSCode [desktop](https://code.visualstudio.com/Download) and [web](https://vscode.dev/). 11 | 12 | ## Features 13 | 14 | * Syntax highlighting 15 | * Snippet completion 16 | * Code formatting 17 | * Code folding 18 | * Code navigation 19 | * Comment toggling 20 | * Bracket autoclosing 21 | * Bracket autosurrounding 22 | * Hover documentation 23 | * Auto Indentation 24 | 25 | ## What it looks like 26 | 27 | ![Settings](images/preview.gif) 28 | 29 | ## Requirements 30 | 31 | * VS Code `1.43.0` or higher 32 | 33 | ## Extension Settings 34 | 35 | 36 | ![Settings](images/settings-preview.png) 37 | 38 | * **`smarty.highlight`**: Enable/disable highlight decoration of smarty tags documents. 39 | * **`smarty.highlightColor`**: Highlight decoration color based on dark/light theme kind. 40 | 41 | **For example:** 42 | 43 | ```jsonc 44 | "smarty.highhlight": true, 45 | "smarty.highlightColor": { 46 | "dark": "#FFFFFF25", 47 | "light": "#FFFA0040" 48 | } 49 | ``` 50 | 51 | ## Formatting Settings 52 | 53 | Here is the list of native vscode settings used in smarty document formatting. 54 | 55 | ```jsonc 56 | { 57 | // The number of spaces a tab is equal to. 58 | "editor.tabSize": 4, 59 | 60 | // Indent using spaces. 61 | "editor.insertSpaces": true, 62 | 63 | // End with a newline. 64 | "html.format.endWithNewline": false, 65 | 66 | // Indent `` and `` sections. 67 | "html.format.indentInnerHtml": false, 68 | 69 | // Maximum number of line breaks to be preserved in one chunk. Use `null` for unlimited. 70 | "html.format.maxPreserveNewLines": null, 71 | 72 | // Controls whether existing line breaks before elements should be preserved. 73 | "html.format.preserveNewLines": true, 74 | 75 | // Wrap attributes. 76 | // - auto: Wrap attributes only when line length is exceeded. 77 | // - force: Wrap each attribute except first. 78 | // - force-aligned: Wrap each attribute except first and keep aligned. 79 | // - force-expand-multiline: Wrap each attribute. 80 | // - aligned-multiple: Wrap when line length is exceeded, align attributes vertically. 81 | // - preserve: Preserve wrapping of attributes. 82 | // - preserve-aligned: Preserve wrapping of attributes but align. 83 | "html.format.wrapAttributes": "auto", 84 | 85 | // Maximum amount of characters per line (0 = disable). 86 | "html.format.wrapLineLength": 120 87 | } 88 | ``` 89 | 90 | ## User Settings 91 | 92 | **For Emmet Abbreviations:** 93 | 94 | Paste the following into your `settings.json` 95 | 96 | ```jsonc 97 | "emmet.includeLanguages": { 98 | "smarty": "html" 99 | } 100 | ``` 101 | 102 | **For Netbeans Style Theme:** 103 | 104 | ![Netbeans Theme](images/netbeans-theme-preview.png) 105 | 106 | Paste the following into your `settings.json` 107 | 108 |
109 | Click to expand settings! 110 | 111 | ```jsonc 112 | "editor.tokenColorCustomizations": { 113 | "textMateRules": [ 114 | { 115 | "scope": [ 116 | "punctuation.section.embedded.begin.smarty", 117 | "punctuation.section.embedded.end.smarty" 118 | ], 119 | "settings": { 120 | "foreground": "#FFA500", 121 | "fontStyle": "bold" 122 | } 123 | }, 124 | { 125 | "scope": [ 126 | "keyword.control.smarty", 127 | "support.function.built-in.smarty" 128 | ], 129 | "settings": { 130 | "foreground": "#16A016", 131 | "fontStyle": "bold" 132 | } 133 | }, 134 | { 135 | "scope": ["variable.parameter.smarty"], 136 | "settings": { 137 | "foreground": "#AE23A3", 138 | "fontStyle": "bold" 139 | } 140 | }, 141 | { 142 | "scope": ["source.smarty"], 143 | "settings": { 144 | "foreground": "#D17C32" 145 | } 146 | } 147 | ] 148 | } 149 | ``` 150 |
151 | 152 | ## Issues 153 | 154 | Submit the [issues](https://github.com/aswinkumar863/smarty-vscode-support/issues) if you find any bug or have any suggestion. 155 | 156 | ## Release Notes 157 | 158 | Detailed release notes are available [here](CHANGELOG.md). 159 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "smarty-template-support", 3 | "displayName": "Smarty Template Support", 4 | "description": "Smarty template support with formatting, folding, snippets, syntax highlighting and more", 5 | "author": { 6 | "name": "Aswin Kumar", 7 | "email": "aswinkumar863@gmail.com" 8 | }, 9 | "license": "MIT", 10 | "publisher": "aswinkumar863", 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/aswinkumar863/smarty-vscode-support.git" 14 | }, 15 | "engines": { 16 | "vscode": "^1.43.0" 17 | }, 18 | "dependencies": { 19 | "vscode-languageclient": "^8.0.1" 20 | }, 21 | "devDependencies": { 22 | "@types/node": "^18.0.0", 23 | "@types/vscode": "^1.68.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /client/src/client.ts: -------------------------------------------------------------------------------- 1 | import * as path from "path"; 2 | import { ExtensionContext, env } from "vscode"; 3 | import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from "vscode-languageclient/node"; 4 | 5 | import * as CONSTANT from "./constants"; 6 | 7 | export function createLanguageClient(context: ExtensionContext) { 8 | // The server is implemented in node 9 | let root = env.uiKind === 1 ? "node" : "web"; 10 | let serverModule = context.asAbsolutePath( 11 | path.join("server", "dist", root, "nodeServerMain.js") 12 | ); 13 | 14 | // The debug options for the server 15 | // --inspect=6009: runs the server in Node"s Inspector mode so VS Code can attach to the server for debugging 16 | let debugOptions = { execArgv: ["--nolazy", "--inspect=6009"] }; 17 | 18 | // If the extension is launched in debug mode then the debug server options are used 19 | // Otherwise the run options are used 20 | let serverOptions: ServerOptions = { 21 | run: { module: serverModule, transport: TransportKind.ipc }, 22 | debug: { 23 | module: serverModule, 24 | transport: TransportKind.ipc, 25 | options: debugOptions 26 | } 27 | }; 28 | 29 | // Options to control the language client 30 | let clientOptions: LanguageClientOptions = { 31 | // Register the server for plain text documents 32 | documentSelector: [CONSTANT.languageId], 33 | initializationOptions: { 34 | dataPaths: [], 35 | embeddedLanguages: { css: true, javascript: true } 36 | } 37 | }; 38 | 39 | // Create the language client. 40 | return new LanguageClient( 41 | CONSTANT.languageId, 42 | CONSTANT.languageServerName, 43 | serverOptions, 44 | clientOptions 45 | ); 46 | } 47 | -------------------------------------------------------------------------------- /client/src/configuration.ts: -------------------------------------------------------------------------------- 1 | import { workspace } from 'vscode'; 2 | import { Configuration, HighlightColorConfig } from "./interfaces"; 3 | 4 | export const CONFIG: Configuration = {}; 5 | 6 | export function setConfiguration(): void { 7 | const getConfig = workspace.getConfiguration(); 8 | 9 | Object.assign(CONFIG, { 10 | highlight: getConfig.get("smarty.highlight"), 11 | highlightColor: getConfig.get("smarty.highlightColor") as HighlightColorConfig, 12 | tabSize: getConfig.get("editor.tabSize"), 13 | insertSpaces: getConfig.get("editor.insertSpaces"), 14 | indentInnerHtml: getConfig.get("html.format.indentInnerHtml"), 15 | maxPreserveNewLines: getConfig.get("html.format.maxPreserveNewLines"), 16 | preserveNewLines: getConfig.get("html.format.preserveNewLines"), 17 | wrapLineLength: getConfig.get("html.format.wrapLineLength"), 18 | wrapAttributes: getConfig.get("html.format.wrapAttributes"), 19 | endWithNewline: getConfig.get("html.format.endWithNewline"), 20 | }); 21 | } -------------------------------------------------------------------------------- /client/src/constants.ts: -------------------------------------------------------------------------------- 1 | export const languageId = "smarty"; 2 | 3 | export const languageServerName = "Smarty Language Server"; 4 | 5 | export const toggleHighlightCommand = "smarty.toggleHighlight"; 6 | 7 | export const lastSeenVersionKey = "lastSeenVersion"; 8 | 9 | export const smartyDocsUri = "https://www.smarty.net/docs/en"; -------------------------------------------------------------------------------- /client/src/extension.ts: -------------------------------------------------------------------------------- 1 | import { commands, ConfigurationTarget, ExtensionContext, languages, window, workspace } from "vscode"; 2 | import { LanguageClient } from "vscode-languageclient/node"; 3 | 4 | import { createLanguageClient } from "./client"; 5 | import { setConfiguration } from "./configuration"; 6 | 7 | import { setLanguageConfiguration } from "./language/configuration"; 8 | import { DocumentLinkProvider } from "./language/documentLink"; 9 | import { HighlightDecoration } from "./language/decoration"; 10 | import { FormattingProvider } from "./language/formatter"; 11 | import { HoverProvider } from "./language/hover"; 12 | 13 | import { promptToShowReleaseNotes } from "./utils"; 14 | import * as CONSTANT from "./constants"; 15 | 16 | let client: LanguageClient; 17 | 18 | export function activate(context: ExtensionContext): void { 19 | 20 | let { activeTextEditor } = window; 21 | 22 | // Set comfiguration 23 | setConfiguration(); 24 | 25 | let smartyDecoration: HighlightDecoration; 26 | 27 | if (activeTextEditor) { 28 | // Create decoration for highlight (if enabled) 29 | smartyDecoration = new HighlightDecoration(activeTextEditor); 30 | setLanguageConfiguration(activeTextEditor); 31 | } 32 | 33 | // Subscribe to document change 34 | window.onDidChangeActiveTextEditor(editor => { 35 | activeTextEditor = editor; 36 | if (editor) { 37 | smartyDecoration?.updateDecorations(activeTextEditor); 38 | setLanguageConfiguration(activeTextEditor); 39 | } 40 | }, null, context.subscriptions); 41 | 42 | workspace.onDidChangeTextDocument(event => { 43 | if (activeTextEditor && event.document === activeTextEditor.document) { 44 | smartyDecoration?.triggerUpdateDecorations(activeTextEditor); 45 | } 46 | }, null, context.subscriptions); 47 | 48 | // Reset 49 | function reset() { 50 | smartyDecoration?.dispose(); 51 | 52 | // reset configuration 53 | setConfiguration(); 54 | 55 | // Receate decoration for highlight (if enabled) 56 | smartyDecoration = new HighlightDecoration(activeTextEditor); 57 | } 58 | 59 | // Subscribe to configuration change 60 | workspace.onDidChangeConfiguration(event => { 61 | const configs: Array = ["editor", "html.format", "smarty"]; 62 | configs.some(config => event.affectsConfiguration(config)) && reset(); 63 | }); 64 | 65 | // Language document formatting providers 66 | languages.registerDocumentFormattingEditProvider(CONSTANT.languageId, new FormattingProvider()); 67 | languages.registerDocumentRangeFormattingEditProvider(CONSTANT.languageId, new FormattingProvider()); 68 | 69 | // Language document link provider 70 | languages.registerDocumentLinkProvider(CONSTANT.languageId, new DocumentLinkProvider()); 71 | 72 | // Language document hover provider 73 | languages.registerHoverProvider(CONSTANT.languageId, new HoverProvider()); 74 | 75 | // Command to toggle highlight decoration 76 | commands.registerCommand(CONSTANT.toggleHighlightCommand, () => { 77 | const getConfig = workspace.getConfiguration('smarty'); 78 | getConfig.update('highlight', !getConfig.get('highlight'), ConfigurationTarget.Global); 79 | }); 80 | 81 | // Prompt to show release notes on extension updated 82 | promptToShowReleaseNotes(context); 83 | 84 | // Create the language client and start the client. 85 | client = createLanguageClient(context); 86 | client.start(); 87 | } 88 | 89 | export function deactivate(): Thenable | undefined { 90 | // Stop the language client. 91 | return client?.stop(); 92 | } -------------------------------------------------------------------------------- /client/src/interfaces.ts: -------------------------------------------------------------------------------- 1 | export interface HighlightColorConfig { 2 | light?: string, 3 | dark?: string 4 | } 5 | 6 | export interface Configuration { 7 | highlight?: boolean, 8 | highlightColor?: HighlightColorConfig, 9 | tabSize?: number, 10 | insertSpaces?: boolean, 11 | indentInnerHtml?: boolean, 12 | maxPreserveNewLines?: number | null, 13 | preserveNewLines?: boolean, 14 | wrapLineLength?: number, 15 | wrapAttributes?: string, 16 | endWithNewline?: boolean 17 | } 18 | 19 | export interface FormattingLiterals { 20 | strings: RegExp, 21 | smartyComment: RegExp, 22 | htmlComment: RegExp, 23 | cssComment: RegExp, 24 | scriptTemplate: RegExp 25 | } 26 | 27 | export interface FormattingTags { 28 | start: Set, 29 | middle: Set, 30 | end: Set 31 | } -------------------------------------------------------------------------------- /client/src/js-beautify/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/bin/css-beautify.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var cli = require('../lib/cli'); cli.interpret(); 3 | 4 | 5 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/bin/html-beautify.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var cli = require('../lib/cli'); cli.interpret(); 3 | 4 | 5 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/bin/js-beautify.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var cli = require('../lib/cli'); 4 | cli.interpret(); -------------------------------------------------------------------------------- /client/src/js-beautify/js/config/defaults.json: -------------------------------------------------------------------------------- 1 | { 2 | "indent_size": 4, 3 | "indent_char": " ", 4 | "indent_level": 0, 5 | "indent_with_tabs": false, 6 | "preserve_newlines": true, 7 | "max_preserve_newlines": 10, 8 | "jslint_happy": false, 9 | "space_after_named_function": false, 10 | "space_after_anon_function": false, 11 | "brace_style": "collapse", 12 | "keep_array_indentation": false, 13 | "keep_function_indentation": false, 14 | "space_before_conditional": true, 15 | "break_chained_methods": false, 16 | "eval_code": false, 17 | "unescape_strings": false, 18 | "wrap_line_length": 0, 19 | "indent_empty_lines": false, 20 | "templating": ["auto"] 21 | } 22 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/index.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true */ 2 | /* globals define */ 3 | /* 4 | The MIT License (MIT) 5 | 6 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation files 10 | (the "Software"), to deal in the Software without restriction, 11 | including without limitation the rights to use, copy, modify, merge, 12 | publish, distribute, sublicense, and/or sell copies of the Software, 13 | and to permit persons to whom the Software is furnished to do so, 14 | subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be 17 | included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | */ 29 | 30 | 'use strict'; 31 | 32 | /** 33 | The following batches are equivalent: 34 | 35 | var beautify_js = require('js-beautify'); 36 | var beautify_js = require('js-beautify').js; 37 | var beautify_js = require('js-beautify').js_beautify; 38 | 39 | var beautify_css = require('js-beautify').css; 40 | var beautify_css = require('js-beautify').css_beautify; 41 | 42 | var beautify_html = require('js-beautify').html; 43 | var beautify_html = require('js-beautify').html_beautify; 44 | 45 | All methods returned accept two arguments, the source string and an options object. 46 | **/ 47 | 48 | function get_beautify(js_beautify, css_beautify, html_beautify) { 49 | // the default is js 50 | var beautify = function(src, config) { 51 | return js_beautify.js_beautify(src, config); 52 | }; 53 | 54 | // short aliases 55 | beautify.js = js_beautify.js_beautify; 56 | beautify.css = css_beautify.css_beautify; 57 | beautify.html = html_beautify.html_beautify; 58 | 59 | // legacy aliases 60 | beautify.js_beautify = js_beautify.js_beautify; 61 | beautify.css_beautify = css_beautify.css_beautify; 62 | beautify.html_beautify = html_beautify.html_beautify; 63 | 64 | return beautify; 65 | } 66 | 67 | if (typeof define === "function" && define.amd) { 68 | // Add support for AMD ( https://github.com/amdjs/amdjs-api/wiki/AMD#defineamd-property- ) 69 | define([ 70 | "./lib/beautify", 71 | "./lib/beautify-css", 72 | "./lib/beautify-html" 73 | ], function(js_beautify, css_beautify, html_beautify) { 74 | return get_beautify(js_beautify, css_beautify, html_beautify); 75 | }); 76 | } else { 77 | (function(mod) { 78 | var beautifier = require('./src/index'); 79 | beautifier.js_beautify = beautifier.js; 80 | beautifier.css_beautify = beautifier.css; 81 | beautifier.html_beautify = beautifier.html; 82 | 83 | mod.exports = get_beautify(beautifier, beautifier, beautifier); 84 | 85 | })(module); 86 | } -------------------------------------------------------------------------------- /client/src/js-beautify/js/lib/unpackers/javascriptobfuscator_unpacker.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 6 | 7 | Permission is hereby granted, free of charge, to any person 8 | obtaining a copy of this software and associated documentation files 9 | (the "Software"), to deal in the Software without restriction, 10 | including without limitation the rights to use, copy, modify, merge, 11 | publish, distribute, sublicense, and/or sell copies of the Software, 12 | and to permit persons to whom the Software is furnished to do so, 13 | subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 22 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | */ 27 | 28 | // 29 | // simple unpacker/deobfuscator for scripts messed up with javascriptobfuscator.com 30 | // written by Einar Lielmanis 31 | // 32 | // usage: 33 | // 34 | // if (JavascriptObfuscator.detect(some_string)) { 35 | // var unpacked = JavascriptObfuscator.unpack(some_string); 36 | // } 37 | // 38 | // 39 | 40 | /*jshint strict:false */ 41 | 42 | var JavascriptObfuscator = { 43 | detect: function(str) { 44 | return /^var _0x[a-f0-9]+ ?\= ?\[/.test(str); 45 | }, 46 | 47 | unpack: function(str) { 48 | if (JavascriptObfuscator.detect(str)) { 49 | var matches = /var (_0x[a-f\d]+) ?\= ?\[(.*?)\];/.exec(str); 50 | if (matches) { 51 | var var_name = matches[1]; 52 | var strings = JavascriptObfuscator._smart_split(matches[2]); 53 | str = str.substring(matches[0].length); 54 | for (var k in strings) { 55 | str = str.replace(new RegExp(var_name + '\\[' + k + '\\]', 'g'), 56 | JavascriptObfuscator._fix_quotes(JavascriptObfuscator._unescape(strings[k]))); 57 | } 58 | } 59 | } 60 | return str; 61 | }, 62 | 63 | _fix_quotes: function(str) { 64 | var matches = /^"(.*)"$/.exec(str); 65 | if (matches) { 66 | str = matches[1]; 67 | str = "'" + str.replace(/'/g, "\\'") + "'"; 68 | } 69 | return str; 70 | }, 71 | 72 | _smart_split: function(str) { 73 | var strings = []; 74 | var pos = 0; 75 | while (pos < str.length) { 76 | if (str.charAt(pos) === '"') { 77 | // new word 78 | var word = ''; 79 | pos += 1; 80 | while (pos < str.length) { 81 | if (str.charAt(pos) === '"') { 82 | break; 83 | } 84 | if (str.charAt(pos) === '\\') { 85 | word += '\\'; 86 | pos++; 87 | } 88 | word += str.charAt(pos); 89 | pos++; 90 | } 91 | strings.push('"' + word + '"'); 92 | } 93 | pos += 1; 94 | } 95 | return strings; 96 | }, 97 | 98 | 99 | _unescape: function(str) { 100 | // inefficient if used repeatedly or on small strings, but wonderful on single large chunk of text 101 | for (var i = 32; i < 128; i++) { 102 | str = str.replace(new RegExp('\\\\x' + i.toString(16), 'ig'), String.fromCharCode(i)); 103 | } 104 | str = str.replace(/\\x09/g, "\t"); 105 | return str; 106 | }, 107 | 108 | run_tests: function(sanity_test) { 109 | var t = sanity_test || new SanityTest(); 110 | 111 | t.test_function(JavascriptObfuscator._smart_split, "JavascriptObfuscator._smart_split"); 112 | t.expect('', []); 113 | t.expect('"a", "b"', ['"a"', '"b"']); 114 | t.expect('"aaa","bbbb"', ['"aaa"', '"bbbb"']); 115 | t.expect('"a", "b\\\""', ['"a"', '"b\\\""']); 116 | t.test_function(JavascriptObfuscator._unescape, 'JavascriptObfuscator._unescape'); 117 | t.expect('\\x40', '@'); 118 | t.expect('\\x10', '\\x10'); 119 | t.expect('\\x1', '\\x1'); 120 | t.expect("\\x61\\x62\\x22\\x63\\x64", 'ab"cd'); 121 | t.test_function(JavascriptObfuscator.detect, 'JavascriptObfuscator.detect'); 122 | t.expect('', false); 123 | t.expect('abcd', false); 124 | t.expect('var _0xaaaa', false); 125 | t.expect('var _0xaaaa = ["a", "b"]', true); 126 | t.expect('var _0xaaaa=["a", "b"]', true); 127 | t.expect('var _0x1234=["a","b"]', true); 128 | return t; 129 | } 130 | 131 | 132 | }; 133 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/lib/unpackers/myobfuscate_unpacker.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 6 | 7 | Permission is hereby granted, free of charge, to any person 8 | obtaining a copy of this software and associated documentation files 9 | (the "Software"), to deal in the Software without restriction, 10 | including without limitation the rights to use, copy, modify, merge, 11 | publish, distribute, sublicense, and/or sell copies of the Software, 12 | and to permit persons to whom the Software is furnished to do so, 13 | subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 22 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | */ 27 | 28 | // 29 | // simple unpacker/deobfuscator for scripts messed up with myobfuscate.com 30 | // You really don't want to obfuscate your scripts there: they're tracking 31 | // your unpackings, your script gets turned into something like this, 32 | // as of 2011-04-25: 33 | /* 34 | 35 | var _escape = 'your_script_escaped'; 36 | var _111 = document.createElement('script'); 37 | _111.src = 'http://api.www.myobfuscate.com/?getsrc=ok' + 38 | '&ref=' + encodeURIComponent(document.referrer) + 39 | '&url=' + encodeURIComponent(document.URL); 40 | var 000 = document.getElementsByTagName('head')[0]; 41 | 000.appendChild(_111); 42 | document.write(unescape(_escape)); 43 | 44 | */ 45 | // 46 | // written by Einar Lielmanis 47 | // 48 | // usage: 49 | // 50 | // if (MyObfuscate.detect(some_string)) { 51 | // var unpacked = MyObfuscate.unpack(some_string); 52 | // } 53 | // 54 | // 55 | 56 | /*jshint strict:false */ 57 | 58 | var MyObfuscate = { 59 | detect: function(str) { 60 | if (/^var _?[0O1lI]{3}\=('|\[).*\)\)\);/.test(str)) { 61 | return true; 62 | } 63 | if (/^function _?[0O1lI]{3}\(_/.test(str) && /eval\(/.test(str)) { 64 | return true; 65 | } 66 | return false; 67 | }, 68 | 69 | unpack: function(str) { 70 | if (MyObfuscate.detect(str)) { 71 | var __eval = eval; 72 | try { 73 | eval = function(unpacked) { // jshint ignore:line 74 | if (MyObfuscate.starts_with(unpacked, 'var _escape')) { 75 | // fetch the urlencoded stuff from the script, 76 | var matches = /'([^']*)'/.exec(unpacked); 77 | var unescaped = unescape(matches[1]); 78 | if (MyObfuscate.starts_with(unescaped, '')) { 82 | unescaped = unescaped.substr(0, unescaped.length - 9); 83 | } 84 | unpacked = unescaped; 85 | } 86 | // throw to terminate the script 87 | unpacked = "// Unpacker warning: be careful when using myobfuscate.com for your projects:\n" + 88 | "// scripts obfuscated by the free online version may call back home.\n" + 89 | "\n//\n" + unpacked; 90 | throw unpacked; 91 | }; // jshint ignore:line 92 | __eval(str); // should throw 93 | } catch (e) { 94 | // well, it failed. we'll just return the original, instead of crashing on user. 95 | if (typeof e === "string") { 96 | str = e; 97 | } 98 | } 99 | eval = __eval; // jshint ignore:line 100 | } 101 | return str; 102 | }, 103 | 104 | starts_with: function(str, what) { 105 | return str.substr(0, what.length) === what; 106 | }, 107 | 108 | ends_with: function(str, what) { 109 | return str.substr(str.length - what.length, what.length) === what; 110 | }, 111 | 112 | run_tests: function(sanity_test) { 113 | var t = sanity_test || new SanityTest(); 114 | 115 | return t; 116 | } 117 | 118 | 119 | }; 120 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/lib/unpackers/p_a_c_k_e_r_unpacker.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 6 | 7 | Permission is hereby granted, free of charge, to any person 8 | obtaining a copy of this software and associated documentation files 9 | (the "Software"), to deal in the Software without restriction, 10 | including without limitation the rights to use, copy, modify, merge, 11 | publish, distribute, sublicense, and/or sell copies of the Software, 12 | and to permit persons to whom the Software is furnished to do so, 13 | subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 22 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | */ 27 | 28 | // 29 | // Unpacker for Dean Edward's p.a.c.k.e.r, a part of javascript beautifier 30 | // 31 | // Coincidentally, it can defeat a couple of other eval-based compressors. 32 | // 33 | // usage: 34 | // 35 | // if (P_A_C_K_E_R.detect(some_string)) { 36 | // var unpacked = P_A_C_K_E_R.unpack(some_string); 37 | // } 38 | // 39 | // 40 | 41 | /*jshint strict:false */ 42 | 43 | var P_A_C_K_E_R = { 44 | detect: function(str) { 45 | return (P_A_C_K_E_R.get_chunks(str).length > 0); 46 | }, 47 | 48 | get_chunks: function(str) { 49 | var chunks = str.match(/eval\(\(?function\(.*?(,0,\{\}\)\)|split\('\|'\)\)\))($|\n)/g); 50 | return chunks ? chunks : []; 51 | }, 52 | 53 | unpack: function(str) { 54 | var chunks = P_A_C_K_E_R.get_chunks(str), 55 | chunk; 56 | for (var i = 0; i < chunks.length; i++) { 57 | chunk = chunks[i].replace(/\n$/, ''); 58 | str = str.split(chunk).join(P_A_C_K_E_R.unpack_chunk(chunk)); 59 | } 60 | return str; 61 | }, 62 | 63 | unpack_chunk: function(str) { 64 | var unpacked_source = ''; 65 | var __eval = eval; 66 | if (P_A_C_K_E_R.detect(str)) { 67 | try { 68 | eval = function(s) { // jshint ignore:line 69 | unpacked_source += s; 70 | return unpacked_source; 71 | }; // jshint ignore:line 72 | __eval(str); 73 | if (typeof unpacked_source === 'string' && unpacked_source) { 74 | str = unpacked_source; 75 | } 76 | } catch (e) { 77 | // well, it failed. we'll just return the original, instead of crashing on user. 78 | } 79 | } 80 | eval = __eval; // jshint ignore:line 81 | return str; 82 | }, 83 | 84 | run_tests: function(sanity_test) { 85 | var t = sanity_test || new SanityTest(); 86 | 87 | var pk1 = "eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String)){while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=function(){return'\\\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\\\b'+e(c)+'\\\\b','g'),k[c]);return p}('0 2=1',3,3,'var||a'.split('|'),0,{}))"; 88 | var unpk1 = 'var a=1'; 89 | var pk2 = "eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String)){while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=function(){return'\\\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\\\b'+e(c)+'\\\\b','g'),k[c]);return p}('0 2=1',3,3,'foo||b'.split('|'),0,{}))"; 90 | var unpk2 = 'foo b=1'; 91 | var pk_broken = "eval(function(p,a,c,k,e,r){BORKBORK;if(!''.replace(/^/,String)){while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=function(){return'\\\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\\\b'+e(c)+'\\\\b','g'),k[c]);return p}('0 2=1',3,3,'var||a'.split('|'),0,{}))"; 92 | var pk3 = "eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String)){while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=function(){return'\\\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\\\b'+e(c)+'\\\\b','g'),k[c]);return p}('0 2=1{}))',3,3,'var||a'.split('|'),0,{}))"; 93 | var unpk3 = 'var a=1{}))'; 94 | 95 | t.test_function(P_A_C_K_E_R.detect, "P_A_C_K_E_R.detect"); 96 | t.expect('', false); 97 | t.expect('var a = b', false); 98 | t.test_function(P_A_C_K_E_R.unpack, "P_A_C_K_E_R.unpack"); 99 | t.expect(pk_broken, pk_broken); 100 | t.expect(pk1, unpk1); 101 | t.expect(pk2, unpk2); 102 | t.expect(pk3, unpk3); 103 | t.expect("function test (){alert ('This is a test!')}; " + 104 | "eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String))" + 105 | "{while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=function" + 106 | "(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp(" + 107 | "'\\b'+e(c)+'\\b','g'),k[c]);return p}('0 2=\\\'{Íâ–+›ï;ã†Ù¥#\\\'',3,3," + 108 | "'var||a'.split('|'),0,{}))", 109 | "function test (){alert ('This is a test!')}; var a='{Íâ–+›ï;ã†Ù¥#'"); 110 | 111 | 112 | var filler = '\nfiller\n'; 113 | t.expect(filler + pk1 + "\n" + pk_broken + filler + pk2 + filler, filler + unpk1 + "\n" + pk_broken + filler + unpk2 + filler); 114 | 115 | return t; 116 | } 117 | 118 | 119 | }; 120 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/lib/unpackers/urlencode_unpacker.js: -------------------------------------------------------------------------------- 1 | /*global unescape */ 2 | /*jshint curly: false, scripturl: true */ 3 | 4 | /* 5 | 6 | The MIT License (MIT) 7 | 8 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 9 | 10 | Permission is hereby granted, free of charge, to any person 11 | obtaining a copy of this software and associated documentation files 12 | (the "Software"), to deal in the Software without restriction, 13 | including without limitation the rights to use, copy, modify, merge, 14 | publish, distribute, sublicense, and/or sell copies of the Software, 15 | and to permit persons to whom the Software is furnished to do so, 16 | subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 25 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 26 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 27 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | */ 30 | 31 | // 32 | // trivial bookmarklet/escaped script detector for the javascript beautifier 33 | // written by Einar Lielmanis 34 | // 35 | // usage: 36 | // 37 | // if (Urlencoded.detect(some_string)) { 38 | // var unpacked = Urlencoded.unpack(some_string); 39 | // } 40 | // 41 | // 42 | 43 | /*jshint strict:false */ 44 | 45 | 46 | var isNode = (typeof module !== 'undefined' && module.exports); 47 | if (isNode) { 48 | var SanityTest = require(__dirname + '/../../test/sanitytest'); 49 | } 50 | 51 | var Urlencoded = { 52 | detect: function(str) { 53 | // the fact that script doesn't contain any space, but has %20 instead 54 | // should be sufficient check for now. 55 | if (str.indexOf(' ') === -1) { 56 | if (str.indexOf('%2') !== -1) return true; 57 | if (str.replace(/[^%]+/g, '').length > 3) return true; 58 | } 59 | return false; 60 | }, 61 | 62 | unpack: function(str) { 63 | if (Urlencoded.detect(str)) { 64 | if (str.indexOf('%2B') !== -1 || str.indexOf('%2b') !== -1) { 65 | // "+" escaped as "%2B" 66 | return unescape(str.replace(/\+/g, '%20')); 67 | } else { 68 | return unescape(str); 69 | } 70 | } 71 | return str; 72 | }, 73 | 74 | 75 | 76 | run_tests: function(sanity_test) { 77 | var t = sanity_test || new SanityTest(); 78 | t.test_function(Urlencoded.detect, "Urlencoded.detect"); 79 | t.expect('', false); 80 | t.expect('var a = b', false); 81 | t.expect('var%20a+=+b', true); 82 | t.expect('var%20a=b', true); 83 | t.expect('var%20%21%22', true); 84 | t.expect('javascript:(function(){var%20whatever={init:function(){alert(%22a%22+%22b%22)}};whatever.init()})();', true); 85 | t.test_function(Urlencoded.unpack, 'Urlencoded.unpack'); 86 | 87 | t.expect('javascript:(function(){var%20whatever={init:function(){alert(%22a%22+%22b%22)}};whatever.init()})();', 88 | 'javascript:(function(){var whatever={init:function(){alert("a"+"b")}};whatever.init()})();' 89 | ); 90 | t.expect('', ''); 91 | t.expect('abcd', 'abcd'); 92 | t.expect('var a = b', 'var a = b'); 93 | t.expect('var%20a=b', 'var a=b'); 94 | t.expect('var%20a=b+1', 'var a=b+1'); 95 | t.expect('var%20a=b%2b1', 'var a=b+1'); 96 | return t; 97 | } 98 | 99 | 100 | }; 101 | 102 | if (isNode) { 103 | module.exports = Urlencoded; 104 | } 105 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/src/core/directives.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true */ 2 | /* 3 | 4 | The MIT License (MIT) 5 | 6 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation files 10 | (the "Software"), to deal in the Software without restriction, 11 | including without limitation the rights to use, copy, modify, merge, 12 | publish, distribute, sublicense, and/or sell copies of the Software, 13 | and to permit persons to whom the Software is furnished to do so, 14 | subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be 17 | included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | */ 28 | 29 | 'use strict'; 30 | 31 | function Directives(start_block_pattern, end_block_pattern) { 32 | start_block_pattern = typeof start_block_pattern === 'string' ? start_block_pattern : start_block_pattern.source; 33 | end_block_pattern = typeof end_block_pattern === 'string' ? end_block_pattern : end_block_pattern.source; 34 | this.__directives_block_pattern = new RegExp(start_block_pattern + / beautify( \w+[:]\w+)+ /.source + end_block_pattern, 'g'); 35 | this.__directive_pattern = / (\w+)[:](\w+)/g; 36 | 37 | this.__directives_end_ignore_pattern = new RegExp(start_block_pattern + /\sbeautify\signore:end\s/.source + end_block_pattern, 'g'); 38 | } 39 | 40 | Directives.prototype.get_directives = function(text) { 41 | if (!text.match(this.__directives_block_pattern)) { 42 | return null; 43 | } 44 | 45 | var directives = {}; 46 | this.__directive_pattern.lastIndex = 0; 47 | var directive_match = this.__directive_pattern.exec(text); 48 | 49 | while (directive_match) { 50 | directives[directive_match[1]] = directive_match[2]; 51 | directive_match = this.__directive_pattern.exec(text); 52 | } 53 | 54 | return directives; 55 | }; 56 | 57 | Directives.prototype.readIgnored = function(input) { 58 | return input.readUntilAfter(this.__directives_end_ignore_pattern); 59 | }; 60 | 61 | 62 | module.exports.Directives = Directives; 63 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/src/core/pattern.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true */ 2 | /* 3 | 4 | The MIT License (MIT) 5 | 6 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation files 10 | (the "Software"), to deal in the Software without restriction, 11 | including without limitation the rights to use, copy, modify, merge, 12 | publish, distribute, sublicense, and/or sell copies of the Software, 13 | and to permit persons to whom the Software is furnished to do so, 14 | subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be 17 | included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | */ 28 | 29 | 'use strict'; 30 | 31 | function Pattern(input_scanner, parent) { 32 | this._input = input_scanner; 33 | this._starting_pattern = null; 34 | this._match_pattern = null; 35 | this._until_pattern = null; 36 | this._until_after = false; 37 | 38 | if (parent) { 39 | this._starting_pattern = this._input.get_regexp(parent._starting_pattern, true); 40 | this._match_pattern = this._input.get_regexp(parent._match_pattern, true); 41 | this._until_pattern = this._input.get_regexp(parent._until_pattern); 42 | this._until_after = parent._until_after; 43 | } 44 | } 45 | 46 | Pattern.prototype.read = function() { 47 | var result = this._input.read(this._starting_pattern); 48 | if (!this._starting_pattern || result) { 49 | result += this._input.read(this._match_pattern, this._until_pattern, this._until_after); 50 | } 51 | return result; 52 | }; 53 | 54 | Pattern.prototype.read_match = function() { 55 | return this._input.match(this._match_pattern); 56 | }; 57 | 58 | Pattern.prototype.until_after = function(pattern) { 59 | var result = this._create(); 60 | result._until_after = true; 61 | result._until_pattern = this._input.get_regexp(pattern); 62 | result._update(); 63 | return result; 64 | }; 65 | 66 | Pattern.prototype.until = function(pattern) { 67 | var result = this._create(); 68 | result._until_after = false; 69 | result._until_pattern = this._input.get_regexp(pattern); 70 | result._update(); 71 | return result; 72 | }; 73 | 74 | Pattern.prototype.starting_with = function(pattern) { 75 | var result = this._create(); 76 | result._starting_pattern = this._input.get_regexp(pattern, true); 77 | result._update(); 78 | return result; 79 | }; 80 | 81 | Pattern.prototype.matching = function(pattern) { 82 | var result = this._create(); 83 | result._match_pattern = this._input.get_regexp(pattern, true); 84 | result._update(); 85 | return result; 86 | }; 87 | 88 | Pattern.prototype._create = function() { 89 | return new Pattern(this._input, this); 90 | }; 91 | 92 | Pattern.prototype._update = function() {}; 93 | 94 | module.exports.Pattern = Pattern; 95 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/src/core/token.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true */ 2 | /* 3 | 4 | The MIT License (MIT) 5 | 6 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation files 10 | (the "Software"), to deal in the Software without restriction, 11 | including without limitation the rights to use, copy, modify, merge, 12 | publish, distribute, sublicense, and/or sell copies of the Software, 13 | and to permit persons to whom the Software is furnished to do so, 14 | subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be 17 | included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | */ 28 | 29 | 'use strict'; 30 | 31 | function Token(type, text, newlines, whitespace_before) { 32 | this.type = type; 33 | this.text = text; 34 | 35 | // comments_before are 36 | // comments that have a new line before them 37 | // and may or may not have a newline after 38 | // this is a set of comments before 39 | this.comments_before = null; /* inline comment*/ 40 | 41 | 42 | // this.comments_after = new TokenStream(); // no new line before and newline after 43 | this.newlines = newlines || 0; 44 | this.whitespace_before = whitespace_before || ''; 45 | this.parent = null; 46 | this.next = null; 47 | this.previous = null; 48 | this.opened = null; 49 | this.closed = null; 50 | this.directives = null; 51 | } 52 | 53 | 54 | module.exports.Token = Token; 55 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/src/core/tokenizer.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true */ 2 | /* 3 | 4 | The MIT License (MIT) 5 | 6 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation files 10 | (the "Software"), to deal in the Software without restriction, 11 | including without limitation the rights to use, copy, modify, merge, 12 | publish, distribute, sublicense, and/or sell copies of the Software, 13 | and to permit persons to whom the Software is furnished to do so, 14 | subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be 17 | included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | */ 28 | 29 | 'use strict'; 30 | 31 | var InputScanner = require('../core/inputscanner').InputScanner; 32 | var Token = require('../core/token').Token; 33 | var TokenStream = require('../core/tokenstream').TokenStream; 34 | var WhitespacePattern = require('./whitespacepattern').WhitespacePattern; 35 | 36 | var TOKEN = { 37 | START: 'TK_START', 38 | RAW: 'TK_RAW', 39 | EOF: 'TK_EOF' 40 | }; 41 | 42 | var Tokenizer = function(input_string, options) { 43 | this._input = new InputScanner(input_string); 44 | this._options = options || {}; 45 | this.__tokens = null; 46 | 47 | this._patterns = {}; 48 | this._patterns.whitespace = new WhitespacePattern(this._input); 49 | }; 50 | 51 | Tokenizer.prototype.tokenize = function() { 52 | this._input.restart(); 53 | this.__tokens = new TokenStream(); 54 | 55 | this._reset(); 56 | 57 | var current; 58 | var previous = new Token(TOKEN.START, ''); 59 | var open_token = null; 60 | var open_stack = []; 61 | var comments = new TokenStream(); 62 | 63 | while (previous.type !== TOKEN.EOF) { 64 | current = this._get_next_token(previous, open_token); 65 | while (this._is_comment(current)) { 66 | comments.add(current); 67 | current = this._get_next_token(previous, open_token); 68 | } 69 | 70 | if (!comments.isEmpty()) { 71 | current.comments_before = comments; 72 | comments = new TokenStream(); 73 | } 74 | 75 | current.parent = open_token; 76 | 77 | if (this._is_opening(current)) { 78 | open_stack.push(open_token); 79 | open_token = current; 80 | } else if (open_token && this._is_closing(current, open_token)) { 81 | current.opened = open_token; 82 | open_token.closed = current; 83 | open_token = open_stack.pop(); 84 | current.parent = open_token; 85 | } 86 | 87 | current.previous = previous; 88 | previous.next = current; 89 | 90 | this.__tokens.add(current); 91 | previous = current; 92 | } 93 | 94 | return this.__tokens; 95 | }; 96 | 97 | 98 | Tokenizer.prototype._is_first_token = function() { 99 | return this.__tokens.isEmpty(); 100 | }; 101 | 102 | Tokenizer.prototype._reset = function() {}; 103 | 104 | Tokenizer.prototype._get_next_token = function(previous_token, open_token) { // jshint unused:false 105 | this._readWhitespace(); 106 | var resulting_string = this._input.read(/.+/g); 107 | if (resulting_string) { 108 | return this._create_token(TOKEN.RAW, resulting_string); 109 | } else { 110 | return this._create_token(TOKEN.EOF, ''); 111 | } 112 | }; 113 | 114 | Tokenizer.prototype._is_comment = function(current_token) { // jshint unused:false 115 | return false; 116 | }; 117 | 118 | Tokenizer.prototype._is_opening = function(current_token) { // jshint unused:false 119 | return false; 120 | }; 121 | 122 | Tokenizer.prototype._is_closing = function(current_token, open_token) { // jshint unused:false 123 | return false; 124 | }; 125 | 126 | Tokenizer.prototype._create_token = function(type, text) { 127 | var token = new Token(type, text, 128 | this._patterns.whitespace.newline_count, 129 | this._patterns.whitespace.whitespace_before_token); 130 | return token; 131 | }; 132 | 133 | Tokenizer.prototype._readWhitespace = function() { 134 | return this._patterns.whitespace.read(); 135 | }; 136 | 137 | 138 | 139 | module.exports.Tokenizer = Tokenizer; 140 | module.exports.TOKEN = TOKEN; 141 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/src/core/tokenstream.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true */ 2 | /* 3 | 4 | The MIT License (MIT) 5 | 6 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation files 10 | (the "Software"), to deal in the Software without restriction, 11 | including without limitation the rights to use, copy, modify, merge, 12 | publish, distribute, sublicense, and/or sell copies of the Software, 13 | and to permit persons to whom the Software is furnished to do so, 14 | subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be 17 | included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | */ 28 | 29 | 'use strict'; 30 | 31 | function TokenStream(parent_token) { 32 | // private 33 | this.__tokens = []; 34 | this.__tokens_length = this.__tokens.length; 35 | this.__position = 0; 36 | this.__parent_token = parent_token; 37 | } 38 | 39 | TokenStream.prototype.restart = function() { 40 | this.__position = 0; 41 | }; 42 | 43 | TokenStream.prototype.isEmpty = function() { 44 | return this.__tokens_length === 0; 45 | }; 46 | 47 | TokenStream.prototype.hasNext = function() { 48 | return this.__position < this.__tokens_length; 49 | }; 50 | 51 | TokenStream.prototype.next = function() { 52 | var val = null; 53 | if (this.hasNext()) { 54 | val = this.__tokens[this.__position]; 55 | this.__position += 1; 56 | } 57 | return val; 58 | }; 59 | 60 | TokenStream.prototype.peek = function(index) { 61 | var val = null; 62 | index = index || 0; 63 | index += this.__position; 64 | if (index >= 0 && index < this.__tokens_length) { 65 | val = this.__tokens[index]; 66 | } 67 | return val; 68 | }; 69 | 70 | TokenStream.prototype.add = function(token) { 71 | if (this.__parent_token) { 72 | token.parent = this.__parent_token; 73 | } 74 | this.__tokens.push(token); 75 | this.__tokens_length += 1; 76 | }; 77 | 78 | module.exports.TokenStream = TokenStream; 79 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/src/core/whitespacepattern.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true */ 2 | /* 3 | 4 | The MIT License (MIT) 5 | 6 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation files 10 | (the "Software"), to deal in the Software without restriction, 11 | including without limitation the rights to use, copy, modify, merge, 12 | publish, distribute, sublicense, and/or sell copies of the Software, 13 | and to permit persons to whom the Software is furnished to do so, 14 | subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be 17 | included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | */ 28 | 29 | 'use strict'; 30 | 31 | var Pattern = require('../core/pattern').Pattern; 32 | 33 | function WhitespacePattern(input_scanner, parent) { 34 | Pattern.call(this, input_scanner, parent); 35 | if (parent) { 36 | this._line_regexp = this._input.get_regexp(parent._line_regexp); 37 | } else { 38 | this.__set_whitespace_patterns('', ''); 39 | } 40 | 41 | this.newline_count = 0; 42 | this.whitespace_before_token = ''; 43 | } 44 | WhitespacePattern.prototype = new Pattern(); 45 | 46 | WhitespacePattern.prototype.__set_whitespace_patterns = function(whitespace_chars, newline_chars) { 47 | whitespace_chars += '\\t '; 48 | newline_chars += '\\n\\r'; 49 | 50 | this._match_pattern = this._input.get_regexp( 51 | '[' + whitespace_chars + newline_chars + ']+', true); 52 | this._newline_regexp = this._input.get_regexp( 53 | '\\r\\n|[' + newline_chars + ']'); 54 | }; 55 | 56 | WhitespacePattern.prototype.read = function() { 57 | this.newline_count = 0; 58 | this.whitespace_before_token = ''; 59 | 60 | var resulting_string = this._input.read(this._match_pattern); 61 | if (resulting_string === ' ') { 62 | this.whitespace_before_token = ' '; 63 | } else if (resulting_string) { 64 | var matches = this.__split(this._newline_regexp, resulting_string); 65 | this.newline_count = matches.length - 1; 66 | this.whitespace_before_token = matches[this.newline_count]; 67 | } 68 | 69 | return resulting_string; 70 | }; 71 | 72 | WhitespacePattern.prototype.matching = function(whitespace_chars, newline_chars) { 73 | var result = this._create(); 74 | result.__set_whitespace_patterns(whitespace_chars, newline_chars); 75 | result._update(); 76 | return result; 77 | }; 78 | 79 | WhitespacePattern.prototype._create = function() { 80 | return new WhitespacePattern(this._input, this); 81 | }; 82 | 83 | WhitespacePattern.prototype.__split = function(regexp, input_string) { 84 | regexp.lastIndex = 0; 85 | var start_index = 0; 86 | var result = []; 87 | var next_match = regexp.exec(input_string); 88 | while (next_match) { 89 | result.push(input_string.substring(start_index, next_match.index)); 90 | start_index = next_match.index + next_match[0].length; 91 | next_match = regexp.exec(input_string); 92 | } 93 | 94 | if (start_index < input_string.length) { 95 | result.push(input_string.substring(start_index, input_string.length)); 96 | } else { 97 | result.push(''); 98 | } 99 | 100 | return result; 101 | }; 102 | 103 | 104 | 105 | module.exports.WhitespacePattern = WhitespacePattern; 106 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/src/css/index.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true */ 2 | /* 3 | 4 | The MIT License (MIT) 5 | 6 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation files 10 | (the "Software"), to deal in the Software without restriction, 11 | including without limitation the rights to use, copy, modify, merge, 12 | publish, distribute, sublicense, and/or sell copies of the Software, 13 | and to permit persons to whom the Software is furnished to do so, 14 | subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be 17 | included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | */ 28 | 29 | 'use strict'; 30 | 31 | var Beautifier = require('./beautifier').Beautifier, 32 | Options = require('./options').Options; 33 | 34 | function css_beautify(source_text, options) { 35 | var beautifier = new Beautifier(source_text, options); 36 | return beautifier.beautify(); 37 | } 38 | 39 | module.exports = css_beautify; 40 | module.exports.defaultOptions = function() { 41 | return new Options(); 42 | }; 43 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/src/css/options.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true */ 2 | /* 3 | 4 | The MIT License (MIT) 5 | 6 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation files 10 | (the "Software"), to deal in the Software without restriction, 11 | including without limitation the rights to use, copy, modify, merge, 12 | publish, distribute, sublicense, and/or sell copies of the Software, 13 | and to permit persons to whom the Software is furnished to do so, 14 | subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be 17 | included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | */ 28 | 29 | 'use strict'; 30 | 31 | var BaseOptions = require('../core/options').Options; 32 | 33 | function Options(options) { 34 | BaseOptions.call(this, options, 'css'); 35 | 36 | this.selector_separator_newline = this._get_boolean('selector_separator_newline', true); 37 | this.newline_between_rules = this._get_boolean('newline_between_rules', true); 38 | var space_around_selector_separator = this._get_boolean('space_around_selector_separator'); 39 | this.space_around_combinator = this._get_boolean('space_around_combinator') || space_around_selector_separator; 40 | 41 | var brace_style_split = this._get_selection_list('brace_style', ['collapse', 'expand', 'end-expand', 'none', 'preserve-inline']); 42 | this.brace_style = 'collapse'; 43 | for (var bs = 0; bs < brace_style_split.length; bs++) { 44 | if (brace_style_split[bs] !== 'expand') { 45 | // default to collapse, as only collapse|expand is implemented for now 46 | this.brace_style = 'collapse'; 47 | } else { 48 | this.brace_style = brace_style_split[bs]; 49 | } 50 | } 51 | } 52 | Options.prototype = new BaseOptions(); 53 | 54 | 55 | 56 | module.exports.Options = Options; 57 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/src/css/tokenizer.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true */ 2 | /* 3 | 4 | The MIT License (MIT) 5 | 6 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation files 10 | (the "Software"), to deal in the Software without restriction, 11 | including without limitation the rights to use, copy, modify, merge, 12 | publish, distribute, sublicense, and/or sell copies of the Software, 13 | and to permit persons to whom the Software is furnished to do so, 14 | subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be 17 | included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | */ 28 | 29 | 'use strict'; 30 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/src/html/index.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true */ 2 | /* 3 | 4 | The MIT License (MIT) 5 | 6 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation files 10 | (the "Software"), to deal in the Software without restriction, 11 | including without limitation the rights to use, copy, modify, merge, 12 | publish, distribute, sublicense, and/or sell copies of the Software, 13 | and to permit persons to whom the Software is furnished to do so, 14 | subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be 17 | included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | */ 28 | 29 | 'use strict'; 30 | 31 | var Beautifier = require('./beautifier').Beautifier, 32 | Options = require('./options').Options; 33 | 34 | function style_html(html_source, options, js_beautify, css_beautify) { 35 | var beautifier = new Beautifier(html_source, options, js_beautify, css_beautify); 36 | return beautifier.beautify(); 37 | } 38 | 39 | module.exports = style_html; 40 | module.exports.defaultOptions = function() { 41 | return new Options(); 42 | }; 43 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/src/html/options.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true */ 2 | /* 3 | 4 | The MIT License (MIT) 5 | 6 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation files 10 | (the "Software"), to deal in the Software without restriction, 11 | including without limitation the rights to use, copy, modify, merge, 12 | publish, distribute, sublicense, and/or sell copies of the Software, 13 | and to permit persons to whom the Software is furnished to do so, 14 | subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be 17 | included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | */ 28 | 29 | 'use strict'; 30 | 31 | var BaseOptions = require('../core/options').Options; 32 | 33 | function Options(options) { 34 | BaseOptions.call(this, options, 'html'); 35 | if (this.templating.length === 1 && this.templating[0] === 'auto') { 36 | this.templating = ['django', 'erb', 'handlebars', 'php', 'smarty']; 37 | } 38 | 39 | this.indent_inner_html = this._get_boolean('indent_inner_html'); 40 | this.indent_body_inner_html = this._get_boolean('indent_body_inner_html', true); 41 | this.indent_head_inner_html = this._get_boolean('indent_head_inner_html', true); 42 | 43 | this.indent_handlebars = this._get_boolean('indent_handlebars', true); 44 | this.wrap_attributes = this._get_selection('wrap_attributes', 45 | ['auto', 'force', 'force-aligned', 'force-expand-multiline', 'aligned-multiple', 'preserve', 'preserve-aligned']); 46 | this.wrap_attributes_indent_size = this._get_number('wrap_attributes_indent_size', this.indent_size); 47 | this.extra_liners = this._get_array('extra_liners', ['head', 'body', '/html']); 48 | 49 | // Block vs inline elements 50 | // https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements 51 | // https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements 52 | // https://www.w3.org/TR/html5/dom.html#phrasing-content 53 | this.inline = this._get_array('inline', [ 54 | 'a', 'abbr', 'area', 'audio', 'b', 'bdi', 'bdo', 'br', 'button', 'canvas', 'cite', 55 | 'code', 'data', 'datalist', 'del', 'dfn', 'em', 'embed', 'i', 'iframe', 'img', 56 | 'input', 'ins', 'kbd', 'keygen', 'label', 'map', 'mark', 'math', 'meter', 'noscript', 57 | 'object', 'output', 'progress', 'q', 'ruby', 's', 'samp', /* 'script', */ 'select', 'small', 58 | 'span', 'strong', 'sub', 'sup', 'svg', 'template', 'textarea', 'time', 'u', 'var', 59 | 'video', 'wbr', 'text', 60 | // obsolete inline tags 61 | 'acronym', 'big', 'strike', 'tt' 62 | ]); 63 | this.void_elements = this._get_array('void_elements', [ 64 | // HTLM void elements - aka self-closing tags - aka singletons 65 | // https://www.w3.org/html/wg/drafts/html/master/syntax.html#void-elements 66 | 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 67 | 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr', 68 | // NOTE: Optional tags are too complex for a simple list 69 | // they are hard coded in _do_optional_end_element 70 | 71 | // Doctype and xml elements 72 | '!doctype', '?xml', 73 | 74 | // obsolete tags 75 | // basefont: https://www.computerhope.com/jargon/h/html-basefont-tag.htm 76 | // isndex: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/isindex 77 | 'basefont', 'isindex' 78 | ]); 79 | this.unformatted = this._get_array('unformatted', []); 80 | this.content_unformatted = this._get_array('content_unformatted', [ 81 | 'pre', 'textarea' 82 | ]); 83 | this.unformatted_content_delimiter = this._get_characters('unformatted_content_delimiter'); 84 | this.indent_scripts = this._get_selection('indent_scripts', ['normal', 'keep', 'separate']); 85 | 86 | } 87 | Options.prototype = new BaseOptions(); 88 | 89 | 90 | 91 | module.exports.Options = Options; 92 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/src/index.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true */ 2 | /* 3 | 4 | The MIT License (MIT) 5 | 6 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation files 10 | (the "Software"), to deal in the Software without restriction, 11 | including without limitation the rights to use, copy, modify, merge, 12 | publish, distribute, sublicense, and/or sell copies of the Software, 13 | and to permit persons to whom the Software is furnished to do so, 14 | subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be 17 | included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | */ 28 | 29 | 'use strict'; 30 | 31 | var js_beautify = require('./javascript/index'); 32 | var css_beautify = require('./css/index'); 33 | var html_beautify = require('./html/index'); 34 | 35 | function style_html(html_source, options, js, css) { 36 | js = js || js_beautify; 37 | css = css || css_beautify; 38 | return html_beautify(html_source, options, js, css); 39 | } 40 | style_html.defaultOptions = html_beautify.defaultOptions; 41 | 42 | module.exports.js = js_beautify; 43 | module.exports.css = css_beautify; 44 | module.exports.html = style_html; 45 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/src/javascript/index.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true */ 2 | /* 3 | 4 | The MIT License (MIT) 5 | 6 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation files 10 | (the "Software"), to deal in the Software without restriction, 11 | including without limitation the rights to use, copy, modify, merge, 12 | publish, distribute, sublicense, and/or sell copies of the Software, 13 | and to permit persons to whom the Software is furnished to do so, 14 | subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be 17 | included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | */ 28 | 29 | 'use strict'; 30 | 31 | var Beautifier = require('./beautifier').Beautifier, 32 | Options = require('./options').Options; 33 | 34 | function js_beautify(js_source_text, options) { 35 | var beautifier = new Beautifier(js_source_text, options); 36 | return beautifier.beautify(); 37 | } 38 | 39 | module.exports = js_beautify; 40 | module.exports.defaultOptions = function() { 41 | return new Options(); 42 | }; 43 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/src/javascript/options.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true */ 2 | /* 3 | 4 | The MIT License (MIT) 5 | 6 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation files 10 | (the "Software"), to deal in the Software without restriction, 11 | including without limitation the rights to use, copy, modify, merge, 12 | publish, distribute, sublicense, and/or sell copies of the Software, 13 | and to permit persons to whom the Software is furnished to do so, 14 | subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be 17 | included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | */ 28 | 29 | 'use strict'; 30 | 31 | var BaseOptions = require('../core/options').Options; 32 | 33 | var validPositionValues = ['before-newline', 'after-newline', 'preserve-newline']; 34 | 35 | function Options(options) { 36 | BaseOptions.call(this, options, 'js'); 37 | 38 | // compatibility, re 39 | var raw_brace_style = this.raw_options.brace_style || null; 40 | if (raw_brace_style === "expand-strict") { //graceful handling of deprecated option 41 | this.raw_options.brace_style = "expand"; 42 | } else if (raw_brace_style === "collapse-preserve-inline") { //graceful handling of deprecated option 43 | this.raw_options.brace_style = "collapse,preserve-inline"; 44 | } else if (this.raw_options.braces_on_own_line !== undefined) { //graceful handling of deprecated option 45 | this.raw_options.brace_style = this.raw_options.braces_on_own_line ? "expand" : "collapse"; 46 | // } else if (!raw_brace_style) { //Nothing exists to set it 47 | // raw_brace_style = "collapse"; 48 | } 49 | 50 | //preserve-inline in delimited string will trigger brace_preserve_inline, everything 51 | //else is considered a brace_style and the last one only will have an effect 52 | 53 | var brace_style_split = this._get_selection_list('brace_style', ['collapse', 'expand', 'end-expand', 'none', 'preserve-inline']); 54 | 55 | this.brace_preserve_inline = false; //Defaults in case one or other was not specified in meta-option 56 | this.brace_style = "collapse"; 57 | 58 | for (var bs = 0; bs < brace_style_split.length; bs++) { 59 | if (brace_style_split[bs] === "preserve-inline") { 60 | this.brace_preserve_inline = true; 61 | } else { 62 | this.brace_style = brace_style_split[bs]; 63 | } 64 | } 65 | 66 | this.unindent_chained_methods = this._get_boolean('unindent_chained_methods'); 67 | this.break_chained_methods = this._get_boolean('break_chained_methods'); 68 | this.space_in_paren = this._get_boolean('space_in_paren'); 69 | this.space_in_empty_paren = this._get_boolean('space_in_empty_paren'); 70 | this.jslint_happy = this._get_boolean('jslint_happy'); 71 | this.space_after_anon_function = this._get_boolean('space_after_anon_function'); 72 | this.space_after_named_function = this._get_boolean('space_after_named_function'); 73 | this.keep_array_indentation = this._get_boolean('keep_array_indentation'); 74 | this.space_before_conditional = this._get_boolean('space_before_conditional', true); 75 | this.unescape_strings = this._get_boolean('unescape_strings'); 76 | this.e4x = this._get_boolean('e4x'); 77 | this.comma_first = this._get_boolean('comma_first'); 78 | this.operator_position = this._get_selection('operator_position', validPositionValues); 79 | 80 | // For testing of beautify preserve:start directive 81 | this.test_output_raw = this._get_boolean('test_output_raw'); 82 | 83 | // force this._options.space_after_anon_function to true if this._options.jslint_happy 84 | if (this.jslint_happy) { 85 | this.space_after_anon_function = true; 86 | } 87 | 88 | } 89 | Options.prototype = new BaseOptions(); 90 | 91 | 92 | 93 | module.exports.Options = Options; 94 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/src/unpackers/javascriptobfuscator_unpacker.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 6 | 7 | Permission is hereby granted, free of charge, to any person 8 | obtaining a copy of this software and associated documentation files 9 | (the "Software"), to deal in the Software without restriction, 10 | including without limitation the rights to use, copy, modify, merge, 11 | publish, distribute, sublicense, and/or sell copies of the Software, 12 | and to permit persons to whom the Software is furnished to do so, 13 | subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 22 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | */ 27 | 28 | // 29 | // simple unpacker/deobfuscator for scripts messed up with javascriptobfuscator.com 30 | // written by Einar Lielmanis 31 | // 32 | // usage: 33 | // 34 | // if (JavascriptObfuscator.detect(some_string)) { 35 | // var unpacked = JavascriptObfuscator.unpack(some_string); 36 | // } 37 | // 38 | // 39 | 40 | /*jshint strict:false */ 41 | 42 | var JavascriptObfuscator = { 43 | detect: function(str) { 44 | return /^var _0x[a-f0-9]+ ?\= ?\[/.test(str); 45 | }, 46 | 47 | unpack: function(str) { 48 | if (JavascriptObfuscator.detect(str)) { 49 | var matches = /var (_0x[a-f\d]+) ?\= ?\[(.*?)\];/.exec(str); 50 | if (matches) { 51 | var var_name = matches[1]; 52 | var strings = JavascriptObfuscator._smart_split(matches[2]); 53 | str = str.substring(matches[0].length); 54 | for (var k in strings) { 55 | str = str.replace(new RegExp(var_name + '\\[' + k + '\\]', 'g'), 56 | JavascriptObfuscator._fix_quotes(JavascriptObfuscator._unescape(strings[k]))); 57 | } 58 | } 59 | } 60 | return str; 61 | }, 62 | 63 | _fix_quotes: function(str) { 64 | var matches = /^"(.*)"$/.exec(str); 65 | if (matches) { 66 | str = matches[1]; 67 | str = "'" + str.replace(/'/g, "\\'") + "'"; 68 | } 69 | return str; 70 | }, 71 | 72 | _smart_split: function(str) { 73 | var strings = []; 74 | var pos = 0; 75 | while (pos < str.length) { 76 | if (str.charAt(pos) === '"') { 77 | // new word 78 | var word = ''; 79 | pos += 1; 80 | while (pos < str.length) { 81 | if (str.charAt(pos) === '"') { 82 | break; 83 | } 84 | if (str.charAt(pos) === '\\') { 85 | word += '\\'; 86 | pos++; 87 | } 88 | word += str.charAt(pos); 89 | pos++; 90 | } 91 | strings.push('"' + word + '"'); 92 | } 93 | pos += 1; 94 | } 95 | return strings; 96 | }, 97 | 98 | 99 | _unescape: function(str) { 100 | // inefficient if used repeatedly or on small strings, but wonderful on single large chunk of text 101 | for (var i = 32; i < 128; i++) { 102 | str = str.replace(new RegExp('\\\\x' + i.toString(16), 'ig'), String.fromCharCode(i)); 103 | } 104 | str = str.replace(/\\x09/g, "\t"); 105 | return str; 106 | }, 107 | 108 | run_tests: function(sanity_test) { 109 | var t = sanity_test || new SanityTest(); 110 | 111 | t.test_function(JavascriptObfuscator._smart_split, "JavascriptObfuscator._smart_split"); 112 | t.expect('', []); 113 | t.expect('"a", "b"', ['"a"', '"b"']); 114 | t.expect('"aaa","bbbb"', ['"aaa"', '"bbbb"']); 115 | t.expect('"a", "b\\\""', ['"a"', '"b\\\""']); 116 | t.test_function(JavascriptObfuscator._unescape, 'JavascriptObfuscator._unescape'); 117 | t.expect('\\x40', '@'); 118 | t.expect('\\x10', '\\x10'); 119 | t.expect('\\x1', '\\x1'); 120 | t.expect("\\x61\\x62\\x22\\x63\\x64", 'ab"cd'); 121 | t.test_function(JavascriptObfuscator.detect, 'JavascriptObfuscator.detect'); 122 | t.expect('', false); 123 | t.expect('abcd', false); 124 | t.expect('var _0xaaaa', false); 125 | t.expect('var _0xaaaa = ["a", "b"]', true); 126 | t.expect('var _0xaaaa=["a", "b"]', true); 127 | t.expect('var _0x1234=["a","b"]', true); 128 | return t; 129 | } 130 | 131 | 132 | }; 133 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/src/unpackers/myobfuscate_unpacker.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 6 | 7 | Permission is hereby granted, free of charge, to any person 8 | obtaining a copy of this software and associated documentation files 9 | (the "Software"), to deal in the Software without restriction, 10 | including without limitation the rights to use, copy, modify, merge, 11 | publish, distribute, sublicense, and/or sell copies of the Software, 12 | and to permit persons to whom the Software is furnished to do so, 13 | subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 22 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | */ 27 | 28 | // 29 | // simple unpacker/deobfuscator for scripts messed up with myobfuscate.com 30 | // You really don't want to obfuscate your scripts there: they're tracking 31 | // your unpackings, your script gets turned into something like this, 32 | // as of 2011-04-25: 33 | /* 34 | 35 | var _escape = 'your_script_escaped'; 36 | var _111 = document.createElement('script'); 37 | _111.src = 'http://api.www.myobfuscate.com/?getsrc=ok' + 38 | '&ref=' + encodeURIComponent(document.referrer) + 39 | '&url=' + encodeURIComponent(document.URL); 40 | var 000 = document.getElementsByTagName('head')[0]; 41 | 000.appendChild(_111); 42 | document.write(unescape(_escape)); 43 | 44 | */ 45 | // 46 | // written by Einar Lielmanis 47 | // 48 | // usage: 49 | // 50 | // if (MyObfuscate.detect(some_string)) { 51 | // var unpacked = MyObfuscate.unpack(some_string); 52 | // } 53 | // 54 | // 55 | 56 | /*jshint strict:false */ 57 | 58 | var MyObfuscate = { 59 | detect: function(str) { 60 | if (/^var _?[0O1lI]{3}\=('|\[).*\)\)\);/.test(str)) { 61 | return true; 62 | } 63 | if (/^function _?[0O1lI]{3}\(_/.test(str) && /eval\(/.test(str)) { 64 | return true; 65 | } 66 | return false; 67 | }, 68 | 69 | unpack: function(str) { 70 | if (MyObfuscate.detect(str)) { 71 | var __eval = eval; 72 | try { 73 | eval = function(unpacked) { // jshint ignore:line 74 | if (MyObfuscate.starts_with(unpacked, 'var _escape')) { 75 | // fetch the urlencoded stuff from the script, 76 | var matches = /'([^']*)'/.exec(unpacked); 77 | var unescaped = unescape(matches[1]); 78 | if (MyObfuscate.starts_with(unescaped, '')) { 82 | unescaped = unescaped.substr(0, unescaped.length - 9); 83 | } 84 | unpacked = unescaped; 85 | } 86 | // throw to terminate the script 87 | unpacked = "// Unpacker warning: be careful when using myobfuscate.com for your projects:\n" + 88 | "// scripts obfuscated by the free online version may call back home.\n" + 89 | "\n//\n" + unpacked; 90 | throw unpacked; 91 | }; // jshint ignore:line 92 | __eval(str); // should throw 93 | } catch (e) { 94 | // well, it failed. we'll just return the original, instead of crashing on user. 95 | if (typeof e === "string") { 96 | str = e; 97 | } 98 | } 99 | eval = __eval; // jshint ignore:line 100 | } 101 | return str; 102 | }, 103 | 104 | starts_with: function(str, what) { 105 | return str.substr(0, what.length) === what; 106 | }, 107 | 108 | ends_with: function(str, what) { 109 | return str.substr(str.length - what.length, what.length) === what; 110 | }, 111 | 112 | run_tests: function(sanity_test) { 113 | var t = sanity_test || new SanityTest(); 114 | 115 | return t; 116 | } 117 | 118 | 119 | }; 120 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/src/unpackers/p_a_c_k_e_r_unpacker.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 6 | 7 | Permission is hereby granted, free of charge, to any person 8 | obtaining a copy of this software and associated documentation files 9 | (the "Software"), to deal in the Software without restriction, 10 | including without limitation the rights to use, copy, modify, merge, 11 | publish, distribute, sublicense, and/or sell copies of the Software, 12 | and to permit persons to whom the Software is furnished to do so, 13 | subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 22 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | */ 27 | 28 | // 29 | // Unpacker for Dean Edward's p.a.c.k.e.r, a part of javascript beautifier 30 | // 31 | // Coincidentally, it can defeat a couple of other eval-based compressors. 32 | // 33 | // usage: 34 | // 35 | // if (P_A_C_K_E_R.detect(some_string)) { 36 | // var unpacked = P_A_C_K_E_R.unpack(some_string); 37 | // } 38 | // 39 | // 40 | 41 | /*jshint strict:false */ 42 | 43 | var P_A_C_K_E_R = { 44 | detect: function(str) { 45 | return (P_A_C_K_E_R.get_chunks(str).length > 0); 46 | }, 47 | 48 | get_chunks: function(str) { 49 | var chunks = str.match(/eval\(\(?function\(.*?(,0,\{\}\)\)|split\('\|'\)\)\))($|\n)/g); 50 | return chunks ? chunks : []; 51 | }, 52 | 53 | unpack: function(str) { 54 | var chunks = P_A_C_K_E_R.get_chunks(str), 55 | chunk; 56 | for (var i = 0; i < chunks.length; i++) { 57 | chunk = chunks[i].replace(/\n$/, ''); 58 | str = str.split(chunk).join(P_A_C_K_E_R.unpack_chunk(chunk)); 59 | } 60 | return str; 61 | }, 62 | 63 | unpack_chunk: function(str) { 64 | var unpacked_source = ''; 65 | var __eval = eval; 66 | if (P_A_C_K_E_R.detect(str)) { 67 | try { 68 | eval = function(s) { // jshint ignore:line 69 | unpacked_source += s; 70 | return unpacked_source; 71 | }; // jshint ignore:line 72 | __eval(str); 73 | if (typeof unpacked_source === 'string' && unpacked_source) { 74 | str = unpacked_source; 75 | } 76 | } catch (e) { 77 | // well, it failed. we'll just return the original, instead of crashing on user. 78 | } 79 | } 80 | eval = __eval; // jshint ignore:line 81 | return str; 82 | }, 83 | 84 | run_tests: function(sanity_test) { 85 | var t = sanity_test || new SanityTest(); 86 | 87 | var pk1 = "eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String)){while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=function(){return'\\\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\\\b'+e(c)+'\\\\b','g'),k[c]);return p}('0 2=1',3,3,'var||a'.split('|'),0,{}))"; 88 | var unpk1 = 'var a=1'; 89 | var pk2 = "eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String)){while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=function(){return'\\\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\\\b'+e(c)+'\\\\b','g'),k[c]);return p}('0 2=1',3,3,'foo||b'.split('|'),0,{}))"; 90 | var unpk2 = 'foo b=1'; 91 | var pk_broken = "eval(function(p,a,c,k,e,r){BORKBORK;if(!''.replace(/^/,String)){while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=function(){return'\\\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\\\b'+e(c)+'\\\\b','g'),k[c]);return p}('0 2=1',3,3,'var||a'.split('|'),0,{}))"; 92 | var pk3 = "eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String)){while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=function(){return'\\\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\\\b'+e(c)+'\\\\b','g'),k[c]);return p}('0 2=1{}))',3,3,'var||a'.split('|'),0,{}))"; 93 | var unpk3 = 'var a=1{}))'; 94 | 95 | t.test_function(P_A_C_K_E_R.detect, "P_A_C_K_E_R.detect"); 96 | t.expect('', false); 97 | t.expect('var a = b', false); 98 | t.test_function(P_A_C_K_E_R.unpack, "P_A_C_K_E_R.unpack"); 99 | t.expect(pk_broken, pk_broken); 100 | t.expect(pk1, unpk1); 101 | t.expect(pk2, unpk2); 102 | t.expect(pk3, unpk3); 103 | t.expect("function test (){alert ('This is a test!')}; " + 104 | "eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String))" + 105 | "{while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=function" + 106 | "(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp(" + 107 | "'\\b'+e(c)+'\\b','g'),k[c]);return p}('0 2=\\\'{Íâ–+›ï;ã†Ù¥#\\\'',3,3," + 108 | "'var||a'.split('|'),0,{}))", 109 | "function test (){alert ('This is a test!')}; var a='{Íâ–+›ï;ã†Ù¥#'"); 110 | 111 | 112 | var filler = '\nfiller\n'; 113 | t.expect(filler + pk1 + "\n" + pk_broken + filler + pk2 + filler, filler + unpk1 + "\n" + pk_broken + filler + unpk2 + filler); 114 | 115 | return t; 116 | } 117 | 118 | 119 | }; 120 | -------------------------------------------------------------------------------- /client/src/js-beautify/js/src/unpackers/urlencode_unpacker.js: -------------------------------------------------------------------------------- 1 | /*global unescape */ 2 | /*jshint curly: false, scripturl: true */ 3 | 4 | /* 5 | 6 | The MIT License (MIT) 7 | 8 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors. 9 | 10 | Permission is hereby granted, free of charge, to any person 11 | obtaining a copy of this software and associated documentation files 12 | (the "Software"), to deal in the Software without restriction, 13 | including without limitation the rights to use, copy, modify, merge, 14 | publish, distribute, sublicense, and/or sell copies of the Software, 15 | and to permit persons to whom the Software is furnished to do so, 16 | subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 25 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 26 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 27 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | */ 30 | 31 | // 32 | // trivial bookmarklet/escaped script detector for the javascript beautifier 33 | // written by Einar Lielmanis 34 | // 35 | // usage: 36 | // 37 | // if (Urlencoded.detect(some_string)) { 38 | // var unpacked = Urlencoded.unpack(some_string); 39 | // } 40 | // 41 | // 42 | 43 | /*jshint strict:false */ 44 | 45 | 46 | var isNode = (typeof module !== 'undefined' && module.exports); 47 | if (isNode) { 48 | var SanityTest = require(__dirname + '/../../test/sanitytest'); 49 | } 50 | 51 | var Urlencoded = { 52 | detect: function(str) { 53 | // the fact that script doesn't contain any space, but has %20 instead 54 | // should be sufficient check for now. 55 | if (str.indexOf(' ') === -1) { 56 | if (str.indexOf('%2') !== -1) return true; 57 | if (str.replace(/[^%]+/g, '').length > 3) return true; 58 | } 59 | return false; 60 | }, 61 | 62 | unpack: function(str) { 63 | if (Urlencoded.detect(str)) { 64 | if (str.indexOf('%2B') !== -1 || str.indexOf('%2b') !== -1) { 65 | // "+" escaped as "%2B" 66 | return unescape(str.replace(/\+/g, '%20')); 67 | } else { 68 | return unescape(str); 69 | } 70 | } 71 | return str; 72 | }, 73 | 74 | 75 | 76 | run_tests: function(sanity_test) { 77 | var t = sanity_test || new SanityTest(); 78 | t.test_function(Urlencoded.detect, "Urlencoded.detect"); 79 | t.expect('', false); 80 | t.expect('var a = b', false); 81 | t.expect('var%20a+=+b', true); 82 | t.expect('var%20a=b', true); 83 | t.expect('var%20%21%22', true); 84 | t.expect('javascript:(function(){var%20whatever={init:function(){alert(%22a%22+%22b%22)}};whatever.init()})();', true); 85 | t.test_function(Urlencoded.unpack, 'Urlencoded.unpack'); 86 | 87 | t.expect('javascript:(function(){var%20whatever={init:function(){alert(%22a%22+%22b%22)}};whatever.init()})();', 88 | 'javascript:(function(){var whatever={init:function(){alert("a"+"b")}};whatever.init()})();' 89 | ); 90 | t.expect('', ''); 91 | t.expect('abcd', 'abcd'); 92 | t.expect('var a = b', 'var a = b'); 93 | t.expect('var%20a=b', 'var a=b'); 94 | t.expect('var%20a=b+1', 'var a=b+1'); 95 | t.expect('var%20a=b%2b1', 'var a=b+1'); 96 | return t; 97 | } 98 | 99 | 100 | }; 101 | 102 | if (isNode) { 103 | module.exports = Urlencoded; 104 | } 105 | -------------------------------------------------------------------------------- /client/src/js-beautify/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_from": "js-beautify", 3 | "_id": "js-beautify@1.13.0", 4 | "_inBundle": false, 5 | "_integrity": "sha512-/Tbp1OVzZjbwzwJQFIlYLm9eWQ+3aYbBXLSaqb1mEJzhcQAfrqMMQYtjb6io+U6KpD0ID4F+Id3/xcjH3l/sqA==", 6 | "_location": "/js-beautify", 7 | "_phantomChildren": {}, 8 | "_requested": { 9 | "type": "tag", 10 | "registry": true, 11 | "raw": "js-beautify", 12 | "name": "js-beautify", 13 | "escapedName": "js-beautify", 14 | "rawSpec": "", 15 | "saveSpec": null, 16 | "fetchSpec": "latest" 17 | }, 18 | "_requiredBy": [ 19 | "#USER", 20 | "/" 21 | ], 22 | "_resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.13.0.tgz", 23 | "_shasum": "a056d5d3acfd4918549aae3ab039f9f3c51eebb2", 24 | "_spec": "js-beautify", 25 | "_where": "D:\\vscode\\temp", 26 | "author": { 27 | "name": "Einar Lielmanis", 28 | "email": "einar@beautifier.io" 29 | }, 30 | "bin": { 31 | "css-beautify": "js/bin/css-beautify.js", 32 | "html-beautify": "js/bin/html-beautify.js", 33 | "js-beautify": "js/bin/js-beautify.js" 34 | }, 35 | "bugs": { 36 | "url": "https://github.com/beautify-web/js-beautify/issues" 37 | }, 38 | "bundleDependencies": false, 39 | "contributors": [ 40 | { 41 | "name": "Vital Batmanov", 42 | "email": "vital76@gmail.com" 43 | }, 44 | { 45 | "name": "Chris J. Shull", 46 | "email": "chrisjshull@gmail.com" 47 | }, 48 | { 49 | "name": "Gian Marco Gherardi", 50 | "email": "gianmarco.gherardi@gmail.com" 51 | }, 52 | { 53 | "name": "Stan", 54 | "email": "stasson@orc.ru" 55 | }, 56 | { 57 | "name": "Vittorio Gambaletta", 58 | "email": "VittGam@vittgam.net" 59 | }, 60 | { 61 | "name": "Daniel Stockman", 62 | "email": "daniel.stockman@gmail.com" 63 | }, 64 | { 65 | "name": "Harutyun Amirjanyan", 66 | "email": "amirjanyan@gmail.com" 67 | }, 68 | { 69 | "name": "Nochum Sossonko", 70 | "email": "nsossonko@hotmail.com" 71 | }, 72 | { 73 | "name": "Liam Newman", 74 | "email": "bitwiseman@beautifier.io" 75 | } 76 | ], 77 | "dependencies": { 78 | "config-chain": "^1.1.12", 79 | "editorconfig": "^0.15.3", 80 | "glob": "^7.1.3", 81 | "mkdirp": "^1.0.4", 82 | "nopt": "^5.0.0" 83 | }, 84 | "deprecated": false, 85 | "description": "beautifier.io for node", 86 | "devDependencies": { 87 | "benchmark": "^2.1.4", 88 | "codemirror": "^5.56.0", 89 | "jquery": "^3.5.1", 90 | "jshint": "^2.12.0", 91 | "minimist": ">=1.2.5", 92 | "mocha": "^8.1.1", 93 | "mustache": "^4.0.1", 94 | "requirejs": "^2.3.6", 95 | "serve": "^11.3.2", 96 | "webpack": "^4.44.1", 97 | "webpack-cli": "^3.3.12" 98 | }, 99 | "directories": { 100 | "lib": "js/lib", 101 | "test": "js/test" 102 | }, 103 | "files": [ 104 | "js/bin/", 105 | "js/lib/*.js", 106 | "js/lib/unpackers/", 107 | "js/index.js", 108 | "js/src/**/*" 109 | ], 110 | "homepage": "https://beautifier.io/", 111 | "keywords": [ 112 | "beautify", 113 | "beautifier", 114 | "code-quality" 115 | ], 116 | "license": "MIT", 117 | "main": "js/index.js", 118 | "name": "js-beautify", 119 | "repository": { 120 | "type": "git", 121 | "url": "git://github.com/beautify-web/js-beautify.git" 122 | }, 123 | "scripts": {}, 124 | "version": "1.13.0" 125 | } 126 | -------------------------------------------------------------------------------- /client/src/language/beautify.ts: -------------------------------------------------------------------------------- 1 | import { FormattingOptions } from 'vscode'; 2 | import { FormattingLiterals, FormattingTags } from "../interfaces"; 3 | import { CONFIG } from "../configuration"; 4 | 5 | const beautify = require("../js-beautify").html; 6 | 7 | export class BeautifySmarty { 8 | 9 | private literals: FormattingLiterals = { 10 | strings: /"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|`(?:\\.|[^`\\])*`/, 11 | smartyComment: /{\*[\s\S]*?\*}/, 12 | htmlComment: //, 13 | cssComment: /\/\*[\s\S]*?\*\//, 14 | scriptTemplate: / 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /server/src/test/fixtures/expected/19813-tab.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /server/src/test/fixtures/expected/19813.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /server/src/test/fixtures/expected/21634.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /server/src/test/fixtures/inputs/19813.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /server/src/test/fixtures/inputs/21634.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /server/src/test/pathCompletionFixtures/.foo.js: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. See License.txt in the project root for license information. 4 | *--------------------------------------------------------------------------------------------*/ -------------------------------------------------------------------------------- /server/src/test/pathCompletionFixtures/about/about.css: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. See License.txt in the project root for license information. 4 | *--------------------------------------------------------------------------------------------*/ -------------------------------------------------------------------------------- /server/src/test/pathCompletionFixtures/about/about.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aswinkumar863/smarty-vscode-support/762950183324f75d9d903de181e5928770c89848/server/src/test/pathCompletionFixtures/about/about.html -------------------------------------------------------------------------------- /server/src/test/pathCompletionFixtures/about/media/icon.pic: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. See License.txt in the project root for license information. 4 | *--------------------------------------------------------------------------------------------*/ -------------------------------------------------------------------------------- /server/src/test/pathCompletionFixtures/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aswinkumar863/smarty-vscode-support/762950183324f75d9d903de181e5928770c89848/server/src/test/pathCompletionFixtures/index.html -------------------------------------------------------------------------------- /server/src/test/pathCompletionFixtures/src/feature.js: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. See License.txt in the project root for license information. 4 | *--------------------------------------------------------------------------------------------*/ -------------------------------------------------------------------------------- /server/src/test/pathCompletionFixtures/src/test.js: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. See License.txt in the project root for license information. 4 | *--------------------------------------------------------------------------------------------*/ -------------------------------------------------------------------------------- /server/src/test/rename.test.ts: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. See License.txt in the project root for license information. 4 | *--------------------------------------------------------------------------------------------*/ 5 | 6 | import * as assert from 'assert'; 7 | import { WorkspaceEdit, TextDocument, getLanguageModes, ClientCapabilities } from '../modes/languageModes'; 8 | import { getNodeFileFS } from '../node/nodeFs'; 9 | 10 | 11 | async function testRename(value: string, newName: string, expectedDocContent: string): Promise { 12 | const offset = value.indexOf('|'); 13 | value = value.substr(0, offset) + value.substr(offset + 1); 14 | 15 | const document = TextDocument.create('test://test/test.html', 'html', 0, value); 16 | const workspace = { 17 | settings: {}, 18 | folders: [{ name: 'foo', uri: 'test://foo' }] 19 | }; 20 | const languageModes = getLanguageModes({ css: true, javascript: true }, workspace, ClientCapabilities.LATEST, getNodeFileFS()); 21 | const javascriptMode = languageModes.getMode('javascript'); 22 | const position = document.positionAt(offset); 23 | 24 | if (javascriptMode) { 25 | const workspaceEdit: WorkspaceEdit | null = await javascriptMode.doRename!(document, position, newName); 26 | 27 | if (!workspaceEdit || !workspaceEdit.changes) { 28 | assert.fail('No workspace edits'); 29 | } 30 | 31 | const edits = workspaceEdit.changes[document.uri.toString()]; 32 | if (!edits) { 33 | assert.fail(`No edits for file at ${document.uri.toString()}`); 34 | } 35 | 36 | const newDocContent = TextDocument.applyEdits(document, edits); 37 | assert.strictEqual(newDocContent, expectedDocContent, `Expected: ${expectedDocContent}\nActual: ${newDocContent}`); 38 | } else { 39 | assert.fail('should have javascriptMode but no'); 40 | } 41 | } 42 | 43 | async function testNoRename(value: string, newName: string): Promise { 44 | const offset = value.indexOf('|'); 45 | value = value.substr(0, offset) + value.substr(offset + 1); 46 | 47 | const document = TextDocument.create('test://test/test.html', 'html', 0, value); 48 | const workspace = { 49 | settings: {}, 50 | folders: [{ name: 'foo', uri: 'test://foo' }] 51 | }; 52 | const languageModes = getLanguageModes({ css: true, javascript: true }, workspace, ClientCapabilities.LATEST, getNodeFileFS()); 53 | const javascriptMode = languageModes.getMode('javascript'); 54 | const position = document.positionAt(offset); 55 | 56 | if (javascriptMode) { 57 | const workspaceEdit: WorkspaceEdit | null = await javascriptMode.doRename!(document, position, newName); 58 | 59 | assert.ok(workspaceEdit?.changes === undefined, 'Should not rename but rename happened'); 60 | } else { 61 | assert.fail('should have javascriptMode but no'); 62 | } 63 | } 64 | 65 | suite('HTML Javascript Rename', () => { 66 | test('Rename Variable', async () => { 67 | const input = [ 68 | '', 69 | '', 70 | '', 74 | '', 75 | '' 76 | ]; 77 | 78 | const output = [ 79 | '', 80 | '', 81 | '', 85 | '', 86 | '' 87 | ]; 88 | 89 | await testRename(input.join('\n'), 'h', output.join('\n')); 90 | }); 91 | 92 | test('Rename Function', async () => { 93 | const input = [ 94 | '', 95 | '', 96 | '', 103 | '', 104 | '' 105 | ]; 106 | 107 | const output = [ 108 | '', 109 | '', 110 | '', 117 | '', 118 | '' 119 | ]; 120 | 121 | await testRename(input.join('\n'), 'sayName', output.join('\n')); 122 | }); 123 | 124 | test('Rename Function Params', async () => { 125 | const input = [ 126 | '', 127 | '', 128 | '', 135 | '', 136 | '' 137 | ]; 138 | 139 | const output = [ 140 | '', 141 | '', 142 | '', 149 | '', 150 | '' 151 | ]; 152 | 153 | await testRename(input.join('\n'), 'newName', output.join('\n')); 154 | }); 155 | 156 | test('Rename Class', async () => { 157 | const input = [ 158 | '', 159 | '', 160 | '', 164 | '', 165 | '' 166 | ]; 167 | 168 | const output = [ 169 | '', 170 | '', 171 | '', 175 | '', 176 | '' 177 | ]; 178 | 179 | await testRename(input.join('\n'), 'Bar', output.join('\n')); 180 | }); 181 | 182 | test('Cannot Rename literal', async () => { 183 | const stringLiteralInput = [ 184 | '', 185 | '', 186 | '', 189 | '', 190 | '' 191 | ]; 192 | const numberLiteralInput = [ 193 | '', 194 | '', 195 | '', 198 | '', 199 | '' 200 | ]; 201 | 202 | await testNoRename(stringLiteralInput.join('\n'), 'something'); 203 | await testNoRename(numberLiteralInput.join('\n'), 'hhhh'); 204 | }); 205 | }); 206 | -------------------------------------------------------------------------------- /server/src/test/selectionRanges.test.ts: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. See License.txt in the project root for license information. 4 | *--------------------------------------------------------------------------------------------*/ 5 | 6 | import 'mocha'; 7 | import * as assert from 'assert'; 8 | import { getLanguageModes, ClientCapabilities, TextDocument, SelectionRange } from '../modes/languageModes'; 9 | import { getSelectionRanges } from '../modes/selectionRanges'; 10 | import { getNodeFileFS } from '../node/nodeFs'; 11 | 12 | async function assertRanges(content: string, expected: (number | string)[][]): Promise { 13 | let message = `${content} gives selection range:\n`; 14 | 15 | const offset = content.indexOf('|'); 16 | content = content.substr(0, offset) + content.substr(offset + 1); 17 | 18 | const workspace = { 19 | settings: {}, 20 | folders: [{ name: 'foo', uri: 'test://foo' }] 21 | }; 22 | const languageModes = getLanguageModes({ css: true, javascript: true }, workspace, ClientCapabilities.LATEST, getNodeFileFS()); 23 | 24 | const document = TextDocument.create('test://foo.html', 'html', 1, content); 25 | const actualRanges = await getSelectionRanges(languageModes, document, [document.positionAt(offset)]); 26 | assert.strictEqual(actualRanges.length, 1); 27 | const offsetPairs: [number, string][] = []; 28 | let curr: SelectionRange | undefined = actualRanges[0]; 29 | while (curr) { 30 | offsetPairs.push([document.offsetAt(curr.range.start), document.getText(curr.range)]); 31 | curr = curr.parent; 32 | } 33 | 34 | message += `${JSON.stringify(offsetPairs)}\n but should give:\n${JSON.stringify(expected)}\n`; 35 | assert.deepStrictEqual(offsetPairs, expected, message); 36 | } 37 | 38 | suite('HTML SelectionRange', () => { 39 | test('Embedded JavaScript', async () => { 40 | await assertRanges('', [ 41 | [48, '1'], 42 | [48, '1+2'], 43 | [47, '(1+2)'], 44 | [47, '(1+2)*6'], 45 | [46, '((1+2)*6)'], 46 | [39, 'return ((1+2)*6)'], 47 | [22, 'function foo() { return ((1+2)*6) }'], 48 | [20, ' function foo() { return ((1+2)*6) }'], 49 | [12, ''], 50 | [6, ''], 51 | [0, ''], 52 | ]); 53 | }); 54 | 55 | test('Embedded CSS', async () => { 56 | await assertRanges('', [ 57 | [34, 'none'], 58 | [25, 'display: none'], 59 | [24, ' display: none; '], 60 | [23, '{ display: none; }'], 61 | [19, 'foo { display: none; }'], 62 | [19, 'foo { display: none; } '], 63 | [12, ''], 64 | [6, ''], 65 | [0, ''], 66 | ]); 67 | }); 68 | 69 | test('Embedded style', async () => { 70 | await assertRanges('
', [ 71 | [19, 'red'], 72 | [12, 'color: red'], 73 | [11, '"color: red"'], 74 | [5, 'style="color: red"'], 75 | [1, 'div style="color: red"'], 76 | [0, '
'] 77 | ]); 78 | }); 79 | 80 | 81 | }); 82 | -------------------------------------------------------------------------------- /server/src/test/words.test.ts: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. See License.txt in the project root for license information. 4 | *--------------------------------------------------------------------------------------------*/ 5 | import * as assert from 'assert'; 6 | import * as words from '../utils/strings'; 7 | import * as fs from 'fs'; 8 | import * as path from 'path'; 9 | 10 | suite('HTML Language Configuration', () => { 11 | const config = JSON.parse((fs.readFileSync(path.join(__dirname, '../../../../html/language-configuration.json')).toString())); 12 | 13 | function createRegex(str: string | { pattern: string; flags: string }): RegExp { 14 | if (typeof str === 'string') { 15 | return new RegExp(str, 'g'); 16 | } 17 | return new RegExp(str.pattern, str.flags); 18 | } 19 | 20 | const wordRegex = createRegex(config.wordPattern); 21 | 22 | function assertWord(value: string, expected: string): void { 23 | const offset = value.indexOf('|'); 24 | value = value.substr(0, offset) + value.substring(offset + 1); 25 | 26 | const actualRange = words.getWordAtText(value, offset, wordRegex); 27 | assert(actualRange.start <= offset); 28 | assert(actualRange.start + actualRange.length >= offset); 29 | assert.strictEqual(value.substr(actualRange.start, actualRange.length), expected); 30 | } 31 | 32 | test('Words Basic', function (): any { 33 | assertWord('|var x1 = new F(a, b);', 'var'); 34 | assertWord('v|ar x1 = new F(a, b);', 'var'); 35 | assertWord('var| x1 = new F(a, b);', 'var'); 36 | assertWord('var |x1 = new F(a, b);', 'x1'); 37 | assertWord('var x1| = new F(a, b);', 'x1'); 38 | assertWord('var x1 = new |F(a, b);', 'F'); 39 | assertWord('var x1 = new F<|A>(a, b);', 'A'); 40 | assertWord('var x1 = new F(|a, b);', 'a'); 41 | assertWord('var x1 = new F(a, b|);', 'b'); 42 | assertWord('var x1 = new F(a, b)|;', ''); 43 | assertWord('var x1 = new F(a, b)|;|', ''); 44 | assertWord('var x1 = | new F(a, b)|;|', ''); 45 | }); 46 | 47 | test('Words Multiline', function (): any { 48 | assertWord('console.log("hello");\n|var x1 = new F(a, b);', 'var'); 49 | assertWord('console.log("hello");\n|\nvar x1 = new F(a, b);', ''); 50 | assertWord('console.log("hello");\n\r |var x1 = new F(a, b);', 'var'); 51 | }); 52 | 53 | const onEnterBeforeRules: RegExp[] = config.onEnterRules.map((r: any) => createRegex(r.beforeText)); 54 | 55 | function assertBeforeRule(text: string, expectedMatch: boolean): void { 56 | for (const reg of onEnterBeforeRules) { 57 | const start = new Date().getTime(); 58 | assert.strictEqual(reg.test(text), expectedMatch); 59 | const totalTime = new Date().getTime() - start; 60 | assert.ok(totalTime < 200, `Evaluation of ${reg.source} on ${text} took ${totalTime}ms]`); 61 | } 62 | } 63 | 64 | test('OnEnter Before', function (): any { 65 | assertBeforeRule('', false); 69 | }); 70 | 71 | }); 72 | -------------------------------------------------------------------------------- /server/src/utils/arrays.ts: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. See License.txt in the project root for license information. 4 | *--------------------------------------------------------------------------------------------*/ 5 | 6 | export function pushAll(to: T[], from: T[]) { 7 | if (from) { 8 | for (const e of from) { 9 | to.push(e); 10 | } 11 | } 12 | } 13 | 14 | export function contains(arr: T[], val: T) { 15 | return arr.indexOf(val) !== -1; 16 | } 17 | 18 | /** 19 | * Like `Array#sort` but always stable. Usually runs a little slower `than Array#sort` 20 | * so only use this when actually needing stable sort. 21 | */ 22 | export function mergeSort(data: T[], compare: (a: T, b: T) => number): T[] { 23 | _divideAndMerge(data, compare); 24 | return data; 25 | } 26 | 27 | function _divideAndMerge(data: T[], compare: (a: T, b: T) => number): void { 28 | if (data.length <= 1) { 29 | // sorted 30 | return; 31 | } 32 | const p = (data.length / 2) | 0; 33 | const left = data.slice(0, p); 34 | const right = data.slice(p); 35 | 36 | _divideAndMerge(left, compare); 37 | _divideAndMerge(right, compare); 38 | 39 | let leftIdx = 0; 40 | let rightIdx = 0; 41 | let i = 0; 42 | while (leftIdx < left.length && rightIdx < right.length) { 43 | const ret = compare(left[leftIdx], right[rightIdx]); 44 | if (ret <= 0) { 45 | // smaller_equal -> take left to preserve order 46 | data[i++] = left[leftIdx++]; 47 | } else { 48 | // greater -> take right 49 | data[i++] = right[rightIdx++]; 50 | } 51 | } 52 | while (leftIdx < left.length) { 53 | data[i++] = left[leftIdx++]; 54 | } 55 | while (rightIdx < right.length) { 56 | data[i++] = right[rightIdx++]; 57 | } 58 | } 59 | 60 | export function binarySearch(array: T[], key: T, comparator: (op1: T, op2: T) => number): number { 61 | let low = 0, 62 | high = array.length - 1; 63 | 64 | while (low <= high) { 65 | const mid = ((low + high) / 2) | 0; 66 | const comp = comparator(array[mid], key); 67 | if (comp < 0) { 68 | low = mid + 1; 69 | } else if (comp > 0) { 70 | high = mid - 1; 71 | } else { 72 | return mid; 73 | } 74 | } 75 | return -(low + 1); 76 | } 77 | -------------------------------------------------------------------------------- /server/src/utils/documentContext.ts: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. See License.txt in the project root for license information. 4 | *--------------------------------------------------------------------------------------------*/ 5 | 6 | import { DocumentContext } from 'vscode-css-languageservice'; 7 | import { endsWith, startsWith } from '../utils/strings'; 8 | import { WorkspaceFolder } from 'vscode-languageserver'; 9 | import { URI, Utils } from 'vscode-uri'; 10 | 11 | export function getDocumentContext(documentUri: string, workspaceFolders: WorkspaceFolder[]): DocumentContext { 12 | function getRootFolder(): string | undefined { 13 | for (const folder of workspaceFolders) { 14 | let folderURI = folder.uri; 15 | if (!endsWith(folderURI, '/')) { 16 | folderURI = folderURI + '/'; 17 | } 18 | if (startsWith(documentUri, folderURI)) { 19 | return folderURI; 20 | } 21 | } 22 | return undefined; 23 | } 24 | 25 | return { 26 | resolveReference: (ref: string, base = documentUri) => { 27 | if (ref.match(/^\w[\w\d+.-]*:/)) { 28 | // starts with a schema 29 | return ref; 30 | } 31 | if (ref[0] === '/') { // resolve absolute path against the current workspace folder 32 | const folderUri = getRootFolder(); 33 | if (folderUri) { 34 | return folderUri + ref.substr(1); 35 | } 36 | } 37 | const baseUri = URI.parse(base); 38 | const baseUriDir = baseUri.path.endsWith('/') ? baseUri : Utils.dirname(baseUri); 39 | return Utils.resolvePath(baseUriDir, ref).toString(true); 40 | }, 41 | }; 42 | } 43 | 44 | -------------------------------------------------------------------------------- /server/src/utils/positions.ts: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. See License.txt in the project root for license information. 4 | *--------------------------------------------------------------------------------------------*/ 5 | 6 | import { Position, Range } from '../modes/languageModes'; 7 | 8 | export function beforeOrSame(p1: Position, p2: Position) { 9 | return p1.line < p2.line || p1.line === p2.line && p1.character <= p2.character; 10 | } 11 | export function insideRangeButNotSame(r1: Range, r2: Range) { 12 | return beforeOrSame(r1.start, r2.start) && beforeOrSame(r2.end, r1.end) && !equalRange(r1, r2); 13 | } 14 | export function equalRange(r1: Range, r2: Range) { 15 | return r1.start.line === r2.start.line && r1.start.character === r2.start.character && r1.end.line === r2.end.line && r1.end.character === r2.end.character; 16 | } 17 | -------------------------------------------------------------------------------- /server/src/utils/runner.ts: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. See License.txt in the project root for license information. 4 | *--------------------------------------------------------------------------------------------*/ 5 | 6 | import { ResponseError, CancellationToken, LSPErrorCodes } from 'vscode-languageserver'; 7 | import { RuntimeEnvironment } from '../htmlServer'; 8 | 9 | export function formatError(message: string, err: any): string { 10 | if (err instanceof Error) { 11 | const error = err; 12 | return `${message}: ${error.message}\n${error.stack}`; 13 | } else if (typeof err === 'string') { 14 | return `${message}: ${err}`; 15 | } else if (err) { 16 | return `${message}: ${err.toString()}`; 17 | } 18 | return message; 19 | } 20 | 21 | export function runSafe(runtime: RuntimeEnvironment, func: () => Thenable, errorVal: T, errorMessage: string, token: CancellationToken): Thenable> { 22 | return new Promise>((resolve) => { 23 | runtime.timer.setImmediate(() => { 24 | if (token.isCancellationRequested) { 25 | resolve(cancelValue()); 26 | return; 27 | } 28 | return func().then(result => { 29 | if (token.isCancellationRequested) { 30 | resolve(cancelValue()); 31 | return; 32 | } else { 33 | resolve(result); 34 | } 35 | }, e => { 36 | console.error(formatError(errorMessage, e)); 37 | resolve(errorVal); 38 | }); 39 | }); 40 | }); 41 | } 42 | 43 | 44 | 45 | function cancelValue() { 46 | return new ResponseError(LSPErrorCodes.RequestCancelled, 'Request cancelled'); 47 | } 48 | -------------------------------------------------------------------------------- /server/src/utils/strings.ts: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. See License.txt in the project root for license information. 4 | *--------------------------------------------------------------------------------------------*/ 5 | 6 | export function getWordAtText(text: string, offset: number, wordDefinition: RegExp): { start: number; length: number } { 7 | let lineStart = offset; 8 | while (lineStart > 0 && !isNewlineCharacter(text.charCodeAt(lineStart - 1))) { 9 | lineStart--; 10 | } 11 | const offsetInLine = offset - lineStart; 12 | const lineText = text.substr(lineStart); 13 | 14 | // make a copy of the regex as to not keep the state 15 | const flags = wordDefinition.ignoreCase ? 'gi' : 'g'; 16 | wordDefinition = new RegExp(wordDefinition.source, flags); 17 | 18 | let match = wordDefinition.exec(lineText); 19 | while (match && match.index + match[0].length < offsetInLine) { 20 | match = wordDefinition.exec(lineText); 21 | } 22 | if (match && match.index <= offsetInLine) { 23 | return { start: match.index + lineStart, length: match[0].length }; 24 | } 25 | 26 | return { start: offset, length: 0 }; 27 | } 28 | 29 | export function startsWith(haystack: string, needle: string): boolean { 30 | if (haystack.length < needle.length) { 31 | return false; 32 | } 33 | 34 | for (let i = 0; i < needle.length; i++) { 35 | if (haystack[i] !== needle[i]) { 36 | return false; 37 | } 38 | } 39 | 40 | return true; 41 | } 42 | 43 | export function endsWith(haystack: string, needle: string): boolean { 44 | const diff = haystack.length - needle.length; 45 | if (diff > 0) { 46 | return haystack.indexOf(needle, diff) === diff; 47 | } else if (diff === 0) { 48 | return haystack === needle; 49 | } else { 50 | return false; 51 | } 52 | } 53 | 54 | export function repeat(value: string, count: number) { 55 | let s = ''; 56 | while (count > 0) { 57 | if ((count & 1) === 1) { 58 | s += value; 59 | } 60 | value += value; 61 | count = count >>> 1; 62 | } 63 | return s; 64 | } 65 | 66 | export function isWhitespaceOnly(str: string) { 67 | return /^\s*$/.test(str); 68 | } 69 | 70 | export function isEOL(content: string, offset: number) { 71 | return isNewlineCharacter(content.charCodeAt(offset)); 72 | } 73 | 74 | const CR = '\r'.charCodeAt(0); 75 | const NL = '\n'.charCodeAt(0); 76 | export function isNewlineCharacter(charCode: number) { 77 | return charCode === CR || charCode === NL; 78 | } -------------------------------------------------------------------------------- /server/src/utils/validation.ts: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. See License.txt in the project root for license information. 4 | *--------------------------------------------------------------------------------------------*/ 5 | 6 | import { CancellationToken, Connection, Diagnostic, Disposable, DocumentDiagnosticParams, DocumentDiagnosticReport, DocumentDiagnosticReportKind, TextDocuments } from 'vscode-languageserver'; 7 | import { TextDocument } from 'vscode-html-languageservice'; 8 | import { formatError, runSafe } from './runner'; 9 | import { RuntimeEnvironment } from '../htmlServer'; 10 | 11 | export type Validator = (textDocument: TextDocument) => Promise; 12 | export type DiagnosticsSupport = { 13 | dispose(): void; 14 | requestRefresh(): void; 15 | }; 16 | 17 | export function registerDiagnosticsPushSupport(documents: TextDocuments, connection: Connection, runtime: RuntimeEnvironment, validate: Validator): DiagnosticsSupport { 18 | 19 | const pendingValidationRequests: { [uri: string]: Disposable } = {}; 20 | const validationDelayMs = 500; 21 | 22 | const disposables: Disposable[] = []; 23 | 24 | // The content of a text document has changed. This event is emitted 25 | // when the text document first opened or when its content has changed. 26 | documents.onDidChangeContent(change => { 27 | triggerValidation(change.document); 28 | }, undefined, disposables); 29 | 30 | // a document has closed: clear all diagnostics 31 | documents.onDidClose(event => { 32 | cleanPendingValidation(event.document); 33 | connection.sendDiagnostics({ uri: event.document.uri, diagnostics: [] }); 34 | }, undefined, disposables); 35 | 36 | function cleanPendingValidation(textDocument: TextDocument): void { 37 | const request = pendingValidationRequests[textDocument.uri]; 38 | if (request) { 39 | request.dispose(); 40 | delete pendingValidationRequests[textDocument.uri]; 41 | } 42 | } 43 | 44 | function triggerValidation(textDocument: TextDocument): void { 45 | cleanPendingValidation(textDocument); 46 | const request = pendingValidationRequests[textDocument.uri] = runtime.timer.setTimeout(async () => { 47 | if (request === pendingValidationRequests[textDocument.uri]) { 48 | try { 49 | const diagnostics = await validate(textDocument); 50 | if (request === pendingValidationRequests[textDocument.uri]) { 51 | connection.sendDiagnostics({ uri: textDocument.uri, diagnostics }); 52 | } 53 | delete pendingValidationRequests[textDocument.uri]; 54 | } catch (e) { 55 | connection.console.error(formatError(`Error while validating ${textDocument.uri}`, e)); 56 | } 57 | } 58 | }, validationDelayMs); 59 | } 60 | 61 | return { 62 | requestRefresh: () => { 63 | documents.all().forEach(triggerValidation); 64 | }, 65 | dispose: () => { 66 | disposables.forEach(d => d.dispose()); 67 | disposables.length = 0; 68 | const keys = Object.keys(pendingValidationRequests); 69 | for (const key of keys) { 70 | pendingValidationRequests[key].dispose(); 71 | delete pendingValidationRequests[key]; 72 | } 73 | } 74 | }; 75 | } 76 | 77 | export function registerDiagnosticsPullSupport(documents: TextDocuments, connection: Connection, runtime: RuntimeEnvironment, validate: Validator): DiagnosticsSupport { 78 | 79 | function newDocumentDiagnosticReport(diagnostics: Diagnostic[]): DocumentDiagnosticReport { 80 | return { 81 | kind: DocumentDiagnosticReportKind.Full, 82 | items: diagnostics 83 | }; 84 | } 85 | 86 | const registration = connection.languages.diagnostics.on(async (params: DocumentDiagnosticParams, token: CancellationToken) => { 87 | return runSafe(runtime, async () => { 88 | const document = documents.get(params.textDocument.uri); 89 | if (document) { 90 | return newDocumentDiagnosticReport(await validate(document)); 91 | } 92 | return newDocumentDiagnosticReport([]); 93 | 94 | }, newDocumentDiagnosticReport([]), `Error while computing diagnostics for ${params.textDocument.uri}`, token); 95 | }); 96 | 97 | function requestRefresh(): void { 98 | connection.languages.diagnostics.refresh(); 99 | } 100 | 101 | return { 102 | requestRefresh, 103 | dispose: () => { 104 | registration.dispose(); 105 | } 106 | }; 107 | 108 | } 109 | -------------------------------------------------------------------------------- /server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "outDir": "out", 8 | "rootDir": "src" 9 | }, 10 | "include": [ 11 | "src/**/*" 12 | ] 13 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "outDir": "out", 6 | "rootDir": "src", 7 | "sourceMap": true 8 | }, 9 | "include": [ 10 | "src" 11 | ], 12 | "exclude": [ 13 | "node_modules", 14 | ".vscode-test" 15 | ], 16 | "references": [ 17 | { "path": "./client" }, 18 | { "path": "./server" } 19 | ] 20 | } -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "indent": [true, "tabs"], 4 | "semicolon": [true, "always"] 5 | } 6 | } --------------------------------------------------------------------------------