├── .gitignore ├── .vscode └── launch.json ├── .vscodeignore ├── LICENCE.md ├── README.md ├── format-html-in-php.gif ├── icon.png ├── package-lock.json ├── package.json ├── src ├── beautifyHtml.ts ├── extension.ts └── optionsFromVsCode.ts ├── tsconfig.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | node_modules 3 | .vscode-test/ 4 | *.vsix 5 | -------------------------------------------------------------------------------- /.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 | "name": "Launch Extension", 7 | "type": "extensionHost", 8 | "request": "launch", 9 | "runtimeExecutable": "${execPath}", 10 | "args": [ 11 | "--extensionDevelopmentPath=${workspaceFolder}" 12 | ], 13 | "outFiles": [ 14 | "${workspaceFolder}/dist/**/*.js" 15 | ], 16 | "preLaunchTask": "npm: webpack" 17 | }, 18 | { 19 | "name": "Extension Tests", 20 | "type": "extensionHost", 21 | "request": "launch", 22 | "runtimeExecutable": "${execPath}", 23 | "args": [ 24 | "--extensionDevelopmentPath=${workspaceFolder}", 25 | "--extensionTestsPath=${workspaceFolder}/out/test" 26 | ], 27 | "outFiles": [ 28 | "${workspaceFolder}/out/test/**/*.js" 29 | ], 30 | "preLaunchTask": "npm: test-compile" 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | src/** 3 | package-json.lock 4 | tsconfig.json 5 | tslint.json 6 | webpack.config.js 7 | -------------------------------------------------------------------------------- /LICENCE.md: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Format HTML in PHP

2 | 3 |

Formatting for the HTML code in PHP files.

4 | 5 | This extension provides formatting for the HTML code in PHP files. This way this works is this extension runs right before the save action which triggers any other registered PHP formatting extensions so you are free to have one and this will not get in the way or block it. 6 | 7 | ![Demo](https://github.com/RiFi2k/format-html-in-php/blob/master/format-html-in-php.gif?raw=true) 8 | 9 | **Supported Features** 10 | 11 | - Uses VSCode configurations for HTML formatting 12 | - Uses VSCode format on save setting 13 | - Custom keybinding for anytime formatting 14 | - Right click context menu option on PHP files 15 | - Command Palette option for formatting 16 | 17 | There are multiple issues and Stackoverflow posts about not being able to format the HTML in PHP files and none of the solutions proposed anywhere really worked 100% so I decided to fix it. 18 | 19 | > Issues, Ideas, Feature Requests? Go ahead and [add them](https://github.com/RiFi2k/format-html-in-php/issues). I'm down to help, add, or fix anything because I know this is badly needed for a lot of PHP / WordPress devs and was a major annoyance for me. 20 | 21 | **Feel free to have nested HTML in .php files now, it will format as you are expecting.** 22 | 23 | --- 24 | 25 | ## Using This Extension 26 | 27 | ### Keybinding 28 | 29 | **CTRL + ALT + F** 30 | 31 | > You can change this if desired through the standard Keyboard Shortcuts (_File > Preferences > Keyboard Shortcuts_) option screen the name is "Format HTML in PHP". 32 | 33 | ### Context Menu 34 | 35 | Within a PHP file you can right click and there is a menu option to Format HTML in PHP. 36 | 37 | ### Format On Save 38 | 39 | Turn on format on save either globally or scoped to PHP. 40 | 41 | ```json 42 | "editor.formatOnSave": false, 43 | "[php]": { 44 | "editor.formatOnSave": true 45 | } 46 | 47 | ``` 48 | 49 | ### HTML Settings 50 | 51 | Here is the list of native vscode settings I pass to JS Beautify which control how your HTML will be formatted. You can change any of these to configure how the HTML will be formatted. 52 | 53 | ```json 54 | "editor.insertSpaces": true, 55 | "editor.tabSize": 4, 56 | "html.format.contentUnformatted": "pre,code,textarea", 57 | "html.format.endWithNewline": false, 58 | "html.format.extraLiners": "head, body, /html", 59 | "html.format.indentHandlebars": false, 60 | "html.format.indentInnerHtml": false, 61 | "html.format.maxPreserveNewLines": null, 62 | "html.format.preserveNewLines": true, 63 | "html.format.wrapLineLength": 120, 64 | "html.format.wrapAttributes": "auto", 65 | ``` 66 | 67 | --- 68 | 69 | ## Install 70 | 71 | See the [extension installation guide](https://code.visualstudio.com/docs/editor/extension-gallery) for details. 72 | 73 | --- 74 | 75 | ## Release Notes 76 | 77 | ### 1.6.3 78 | 79 | - JS Beautify to stable 1.12.0 80 | 81 | ### 1.6.2 82 | 83 | - JS Beautify to stable 1.10.3 84 | 85 | ### 1.6.1 86 | 87 | - JS Beautify to stable 1.10.1 88 | 89 | ### 1.5.3 90 | 91 | - JS Beautify to stable 1.9.0 92 | 93 | ### 1.5.2 94 | 95 | - Documentation update about HTML settings - [#17](https://github.com/RiFi2k/format-html-in-php/issues/17) 96 | - JS Beautify bump to latest beta 97 | 98 | ### 1.5.0 99 | 100 | - Updating to the new JS Beautify version. If anyone notices any issues let me know! 101 | - Upstream fixes [#14](https://github.com/RiFi2k/format-html-in-php/issues/14) - Don't format { 16 | const editor = vscode.window.activeTextEditor; 17 | if (editor.document.languageId === 'php') { 18 | const cursor = editor.selection.active; 19 | const last = editor.document.lineAt(editor.document.lineCount - 1); 20 | const range = new vscode.Range( 21 | new vscode.Position(0, 0), 22 | last.range.end 23 | ); 24 | event.waitUntil(this.doPreSaveTransformations( 25 | event.document, 26 | event.reason 27 | ).then((content) => { 28 | editor.edit(edit => { 29 | if (content !== '') { 30 | edit.replace(range, content); 31 | } 32 | }).then(success => { 33 | if (success && content !== '') { 34 | const origSelection = new vscode.Selection(cursor, cursor); 35 | editor.selection = origSelection; 36 | } 37 | }); 38 | })); 39 | } 40 | })); 41 | this.disposable = vscode.Disposable.from.apply(this, subscriptions); 42 | } 43 | 44 | public dispose() { 45 | this.disposable.dispose(); 46 | } 47 | 48 | private async doPreSaveTransformations( 49 | doc: vscode.TextDocument, 50 | reason: vscode.TextDocumentSaveReason 51 | ): Promise { 52 | const config = vscode.workspace.getConfiguration(); 53 | const phpScopedFormat = has(config, '[php]'); 54 | let phpScopedFormatVal = false; 55 | if (phpScopedFormat) { 56 | const phpScopedObj = get(config, '[php]'); 57 | if (phpScopedObj['editor.formatOnSave']) { 58 | phpScopedFormatVal = true; 59 | } 60 | } 61 | if (config.editor.formatOnSave === true || phpScopedFormatVal === true) { 62 | const html = vscode.window.activeTextEditor.document.getText(); 63 | const options = optionsFromVSCode(config); 64 | return beautifyHtml(html, options); 65 | } 66 | return ''; 67 | } 68 | 69 | } 70 | 71 | export function activate(formatHtmlInPhp: vscode.ExtensionContext) { 72 | const docWatch = new DocumentWatcher(); 73 | formatHtmlInPhp.subscriptions.push(docWatch); 74 | formatHtmlInPhp.subscriptions.push(vscode.commands.registerCommand('formatHtmlInPhp.format', () => { 75 | const editor = vscode.window.activeTextEditor; 76 | const config = vscode.workspace.getConfiguration(); 77 | const cursor = editor.selection.active; 78 | const last = editor.document.lineAt(editor.document.lineCount - 1); 79 | const range = new vscode.Range( 80 | new vscode.Position(0, 0), 81 | last.range.end 82 | ); 83 | const html = vscode.window.activeTextEditor.document.getText(); 84 | const options = optionsFromVSCode(config); 85 | const formattedHtml = beautifyHtml(html, options); 86 | editor.edit(edit => { 87 | edit.replace(range, formattedHtml); 88 | }).then(success => { 89 | if (success) { 90 | const origSelection = new vscode.Selection(cursor, cursor); 91 | editor.selection = origSelection; 92 | } 93 | }); 94 | })); 95 | } 96 | -------------------------------------------------------------------------------- /src/optionsFromVsCode.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function arrayUnique(dirtyArray) { 4 | var a = dirtyArray.concat(); 5 | for(var i=0; i s.trim()); 20 | } else { 21 | extraLinersVal = config.html.format.extraLiners; 22 | } 23 | 24 | let contentUnformattedVal; 25 | if (typeof config.html.format.contentUnformatted === 'string') { 26 | contentUnformattedVal = config.html.format.contentUnformatted 27 | .split(",") 28 | .map(s => s.trim()); 29 | } else { 30 | contentUnformattedVal = config.html.format.contentUnformatted; 31 | } 32 | 33 | const defaultContentUnformatted = []; 34 | 35 | let indentTabs; 36 | if (config.editor.insertSpaces === true) { 37 | indentTabs = false; 38 | } else { 39 | indentTabs = true; 40 | } 41 | 42 | const options = { 43 | indent_with_tabs: indentTabs, 44 | indent_size: config.editor.tabSize, 45 | indent_char: " ", 46 | extra_liners: extraLinersVal, 47 | content_unformatted: arrayUnique(defaultContentUnformatted.concat(contentUnformattedVal)), 48 | indent_handlebars: config.html.format.indentHandlebars, 49 | indent_inner_html: config.html.format.indentInnerHtml, 50 | max_preserve_newlines: config.html.format.maxPreserveNewLines, 51 | preserve_newlines: config.html.format.preserveNewLines, 52 | wrap_line_length: config.html.format.wrapLineLength, 53 | wrap_attributes: config.html.format.wrapAttributes, 54 | indent_scripts: "keep", 55 | html: { 56 | end_with_newline: config.html.format.endWithNewline, 57 | js: { 58 | templating: "php", 59 | end_with_newline: false 60 | } 61 | } 62 | }; 63 | 64 | return options; 65 | } 66 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "outDir": "out", 6 | "lib": [ 7 | "es6" 8 | ], 9 | "sourceMap": true, 10 | "rootDir": "src", 11 | "strict": false, 12 | "noUnusedLocals": true 13 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 14 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 15 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 16 | }, 17 | "exclude": [ 18 | "node_modules", 19 | ".vscode-test" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-string-throw": true, 4 | "no-unused-expression": true, 5 | "no-duplicate-variable": true, 6 | "curly": true, 7 | "class-name": true, 8 | "semicolon": [ 9 | true, 10 | "always" 11 | ], 12 | "triple-equals": true 13 | }, 14 | "defaultSeverity": "warning" 15 | } --------------------------------------------------------------------------------