mirror of
https://github.com/pojokcodeid/nvim-lazy.git
synced 2025-06-23 09:18:44 +02:00
update
This commit is contained in:
parent
e53a643e3d
commit
1ab37bd478
209 changed files with 79957 additions and 0 deletions
13
my-snippets/laravel-blade/.editorconfig
Normal file
13
my-snippets/laravel-blade/.editorconfig
Normal file
|
@ -0,0 +1,13 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.json]
|
||||
indent_style = space
|
||||
indent_size = 2
|
6
my-snippets/laravel-blade/.gitignore
vendored
Normal file
6
my-snippets/laravel-blade/.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
out
|
||||
node_modules
|
||||
*.vsix
|
||||
**/*.log
|
||||
.vscode/tests/
|
||||
**/temp/
|
19
my-snippets/laravel-blade/.vscode/launch.json
vendored
Normal file
19
my-snippets/laravel-blade/.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
// A launch configuration that launches the extension inside a new window
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch Extension",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceRoot}"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceRoot}/out/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "npm"
|
||||
}
|
||||
]
|
||||
}
|
4
my-snippets/laravel-blade/.vscode/settings.json
vendored
Normal file
4
my-snippets/laravel-blade/.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"emmet.triggerExpansionOnTab": true,
|
||||
"blade.format.enable": true
|
||||
}
|
15
my-snippets/laravel-blade/.vscode/tasks.json
vendored
Normal file
15
my-snippets/laravel-blade/.vscode/tasks.json
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"version": "2.0.0",
|
||||
"type": "shell",
|
||||
"command": "npm",
|
||||
// run the custom script "compile" as defined in package.json
|
||||
"args": [
|
||||
"run",
|
||||
"compile",
|
||||
"--loglevel",
|
||||
"silent"
|
||||
],
|
||||
"isBackground": true,
|
||||
// The tsc compiler is started in watching mode
|
||||
"problemMatcher": "$tsc-watch"
|
||||
}
|
18
my-snippets/laravel-blade/.vscodeignore
Normal file
18
my-snippets/laravel-blade/.vscodeignore
Normal file
|
@ -0,0 +1,18 @@
|
|||
.vscode/**/*
|
||||
.gitignore
|
||||
tests/**/*
|
||||
.vscode-test/**
|
||||
out/test/**
|
||||
test/**
|
||||
src/**
|
||||
**/*.map
|
||||
tsconfig.json
|
||||
vsc-extension-quickstart.md
|
||||
server/src/**
|
||||
server/lib/**
|
||||
server/*.json
|
||||
server/node_modules/.bin/
|
||||
webpack.config.js
|
||||
node_modules/**
|
||||
**/*.ts
|
||||
**/tsconfig.json
|
253
my-snippets/laravel-blade/CHANGELOG.md
Normal file
253
my-snippets/laravel-blade/CHANGELOG.md
Normal file
|
@ -0,0 +1,253 @@
|
|||
## 1.32.0
|
||||
|
||||
- Add `@disabled` directive and `b:disabled` snippet ([@JustinByrne](https://github.com/JustinByrne) - [PR #151](https://github.com/onecentlin/laravel-blade-snippets-vscode/pull/151))
|
||||
- Add `b:class` snippet (PR #136 and PR #140 - Thanks to [@lakuapik](https://github.com/lakuapik) and [@wilsenhc](https://github.com/wilsenhc))
|
||||
|
||||
## 1.31.0
|
||||
|
||||
- Add `b:aware` and `b:js` snippet
|
||||
- Add `@aware` directive ([Laravel 8.64](https://laravel-news.com/laravel-8-64-0))
|
||||
- Add `@js` directive ([Laravel 8.71](https://laravel-news.com/laravel-8-71-0))
|
||||
- Update `Blade::render` and `Blade::renderComponent` snippet
|
||||
|
||||
## 1.30.0
|
||||
|
||||
Add Laravel 9 features
|
||||
|
||||
- Add `b:checked` and `b:selected` snippet
|
||||
- Add `@checked` and `@selected` directive syntax highlight
|
||||
- Add `Blade::render` and `Blade::renderComponent` snippet
|
||||
|
||||
## 1.29.0
|
||||
|
||||
Happy New Year 2022!
|
||||
|
||||
- Add `b:canany` and `b:canany-cananyelse` snippet ([@JustinByrne](https://github.com/JustinByrne) - [PR #144](https://github.com/onecentlin/laravel-blade-snippets-vscode/pull/144))
|
||||
- Fix snippet
|
||||
- Update blade syntaxes
|
||||
- Update packages
|
||||
|
||||
## 1.28.0
|
||||
|
||||
- Added support attribute expressions syntax highlighting ([@cpof-tea](https://github.com/cpof-tea) - [PR #138](https://github.com/onecentlin/laravel-blade-snippets-vscode/pull/138))
|
||||
|
||||
## 1.27.0
|
||||
|
||||
- Add `@class` directive syntax highlight
|
||||
- Update blade syntaxes
|
||||
- Fix snippet
|
||||
|
||||
## 1.26.0
|
||||
|
||||
- Add `b:once` snippet ([@lakuapik](https://github.com/lakuapik) - [PR #137](https://github.com/onecentlin/laravel-blade-snippets-vscode/pull/137))
|
||||
- Add `Blade::stringable` snippet ([@lakuapik](https://github.com/lakuapik) - [PR #135](https://github.com/onecentlin/laravel-blade-snippets-vscode/pull/135))
|
||||
- Update packages
|
||||
|
||||
## 1.25.0
|
||||
|
||||
- Add `@once` directive
|
||||
- Fix ([#121](https://github.com/onecentlin/laravel-blade-snippets-vscode/issues/121) @php() highlighting
|
||||
- Update blade syntaxes
|
||||
|
||||
## 1.24.0
|
||||
|
||||
- Update blade syntaxes
|
||||
|
||||
## 1.23.0
|
||||
|
||||
- Add `@livewireStyles`, `@livewireScripts`, `@livewire` directive (v8.x)
|
||||
- Add `livewire:styles`, `livewire:scripts`, `livewire:component` snippets
|
||||
- Cleanup snippets
|
||||
|
||||
## 1.22.0
|
||||
|
||||
- Add `@includeUnless` directive (v6.x)
|
||||
- Add environment directives: `@production`, `@env` (v7.x)
|
||||
- Rename language mode using `Blade` instead of `Laravel Blade`
|
||||
- Enable language feature in blade language mode
|
||||
- Reduce extension package size
|
||||
|
||||
## 1.21.0
|
||||
|
||||
- Add `b:error` snippets ([@CaddyDz](https://github.com/CaddyDz) - [PR #95](https://github.com/onecentlin/laravel-blade-snippets-vscode/pull/95))
|
||||
- Add `b:props` snippets
|
||||
- Add blade extensions snippets
|
||||
- `Blade::component`
|
||||
- `Blade::include`
|
||||
- `Blade::if`
|
||||
- `Blade::directive`
|
||||
|
||||
## 1.20.0
|
||||
|
||||
- Update blade formatter fixed for updated languageservice
|
||||
|
||||
## 1.19.0
|
||||
|
||||
- Append html format options to html formatter ([@ayatkyo](https://github.com/ayatkyo) - [PR #87](https://github.com/onecentlin/laravel-blade-snippets-vscode/pull/87))
|
||||
- Update package dependencies
|
||||
|
||||
## 1.18.0
|
||||
|
||||
- Add `b:csrf`, `b:method`, `b:dump` snipptes ([@HasanAlyazidi](https://github.com/HasanAlyazidi) - [PR #60](https://github.com/onecentlin/laravel-blade-snippets-vscode/pull/60))
|
||||
- Fix comment with extra spaces (#59)
|
||||
- Fix formatting issue in url syntax (#57)
|
||||
- Fix shorthand `@php()` for Roots/Sage WordPress Template with html tag syntax highlight (#53)
|
||||
|
||||
## 1.17.0
|
||||
|
||||
- Syntax highlighting enhancement
|
||||
- Add syntax highlighting for class static method
|
||||
- Add `b:lang` snippet (#52)
|
||||
|
||||
## 1.16.0
|
||||
|
||||
- Fix tag attributes completition (#24)
|
||||
- Fix comment issue in `script`, `style`, `php` block with `Ctrl + /` or `⌘ + /` keymap shortcut (#25, #34)
|
||||
|
||||
## 1.15.0
|
||||
|
||||
- Support Envoy directives: `@setup`, `@servers`, `@task`, `@story`, `@finished`, `@slack` (#41)
|
||||
|
||||
## 1.14.2
|
||||
|
||||
- Fix error in Blade Language Server (#46)
|
||||
- Fix extensionPath of undefined (#47)
|
||||
- Emmet setting changed (#48)
|
||||
> Settings below for blade is no longer needed.
|
||||
>```json
|
||||
>"emmet.includeLanguages": {
|
||||
> "blade": "html"
|
||||
>},
|
||||
>```
|
||||
|
||||
## 1.14.0
|
||||
|
||||
- Fix blade syntax broken with VSCode 1.20.0 release (#42)
|
||||
- Modify the highlight, add to the style and script autocomplete ([@tiansin](https://github.com/tiansin) - [PR #43](https://github.com/onecentlin/laravel-blade-snippets-vscode/pull/43))
|
||||
- Fix javascript autocompletion not working in script tag (#39)
|
||||
- Add `b:unless` snippet
|
||||
|
||||
## 1.13.0
|
||||
|
||||
- Fix spaces on format (#40)
|
||||
- Enable format selection (#10)
|
||||
- Enhance blade format (#32, #36)
|
||||
|
||||
## 1.12.0
|
||||
|
||||
- Add `blade.format.enable` configuration setting for manual enable blade file format. (#30)
|
||||
```json
|
||||
"blade.format.enable": true,
|
||||
```
|
||||
- Add `@includeFirst` directive
|
||||
- Add `b:includeFirst` snippet
|
||||
- Fix minor syntax issue
|
||||
|
||||
## 1.11.0
|
||||
|
||||
- Fix indent issue #9, #35 ([@izcream](https://github.com/izcream) - [PR #38](https://github.com/onecentlin/laravel-blade-snippets-vscode/pull/38))
|
||||
- Fix minor whitespace inconsistencies ([@raniesantos](https://github.com/raniesantos) - [PR #28](https://github.com/onecentlin/laravel-blade-snippets-vscode/pull/28/files))
|
||||
|
||||
## 1.10.0
|
||||
|
||||
- Update syntax highlighting
|
||||
- Added `Document Highlight Provider` and `Document Format Provider` ([@TheColorRed](https://github.com/TheColorRed) - [PR #17](https://github.com/onecentlin/laravel-blade-snippets-vscode/pull/17))
|
||||
|
||||
## 1.9.0
|
||||
|
||||
Laravel 5.4 blade directives & snippets:
|
||||
|
||||
- Add `@isset`, `@empty`, `@includeWhen` directives
|
||||
- Add `b:isset`, `b:empty`, `b:includeWhen` snippets
|
||||
|
||||
Laravel 5.5 blade directives & snippets:
|
||||
|
||||
- Add `@auth`, `@guest`, `@switch`, `@case`, `@default` directives
|
||||
- Add `b:auth`, `b:guest`, `b:switch` snippets
|
||||
|
||||
Syntax Enhancement
|
||||
|
||||
- Change grammar of blade directive ([@mikebronner](https://github.com/mikebronner) - [PR #23](https://github.com/onecentlin/laravel-blade-snippets-vscode/pull/23))
|
||||
|
||||
## 1.8.2
|
||||
|
||||
- Update README ([#18](https://github.com/onecentlin/laravel-blade-snippets-vscode/issues/18), [#19](https://github.com/onecentlin/laravel-blade-snippets-vscode/pull/19))
|
||||
|
||||
## 1.8.1
|
||||
|
||||
- Fix syntax parse failed [#5](https://github.com/onecentlin/laravel-blade-snippets-vscode/issues/5)
|
||||
|
||||
## 1.8.0
|
||||
|
||||
- Add `@can` and `@cannot` related directives ([#4](https://github.com/onecentlin/laravel-blade-snippets-vscode/issues/4))
|
||||
- Add `b:can`, `b:can-elsecan`, `b:cannot`, `b:cannot-elsecannot` authorizing snippets ([#4](https://github.com/onecentlin/laravel-blade-snippets-vscode/issues/4))
|
||||
- Add `lv:mix` helper
|
||||
- Fix for loop snippet
|
||||
|
||||
## 1.7.0
|
||||
|
||||
- Enhance blade syntax highlighting
|
||||
- Fix loop snippets
|
||||
|
||||
## 1.6.1
|
||||
|
||||
- Fix extra slashes in `lv:*` helper snippets
|
||||
|
||||
## 1.6
|
||||
|
||||
- Support `@component` and `@slot` directive added in Laravel 5.4
|
||||
- Fix [#3](https://github.com/onecentlin/laravel-blade-snippets-vscode/issues/3) issue
|
||||
|
||||
## 1.5
|
||||
|
||||
Support new directive added in Laravel 5.3
|
||||
|
||||
### PHP
|
||||
|
||||
In some situations, it's useful to embed PHP code into your views. You can use the Blade `@php` directive to execute a block of plain PHP within your template:
|
||||
|
||||
```
|
||||
@php
|
||||
//
|
||||
@endphp
|
||||
```
|
||||
|
||||
### Include Sub-views
|
||||
|
||||
If you attempt to `@include` a view which does not exist, Laravel will throw an error. If you would like to include a view that may or may not be present, you should use the `@includeIf` directive:
|
||||
|
||||
```
|
||||
@includeIf('view.name', ['some' => 'data'])
|
||||
```
|
||||
|
||||
## 1.4
|
||||
|
||||
Update language mode recognition and emmet setting for VS Code 1.5+
|
||||
|
||||
## 1.3
|
||||
|
||||
Support Laravel 5.3 blade syntax
|
||||
|
||||
* `@verbatim` - displaying JavaScript variables in a large portion in template
|
||||
|
||||
```
|
||||
@verbatim
|
||||
<div class="container">
|
||||
Hello, {{ name }}.
|
||||
</div>
|
||||
@endverbatim
|
||||
```
|
||||
|
||||
* `$loop` variable : index, remaining, count, first, last, depth, parent
|
||||
|
||||
```
|
||||
$loop->index
|
||||
$loop->remaining
|
||||
$loop->count
|
||||
$loop->first
|
||||
$loop->last
|
||||
$loop->depth
|
||||
$loop->parent
|
||||
```
|
||||
|
||||
* Add pagination links helper snippet: `lv:pagination-links`
|
9
my-snippets/laravel-blade/LICENSE.md
Normal file
9
my-snippets/laravel-blade/LICENSE.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Winnie Lin
|
||||
|
||||
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:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
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.
|
149
my-snippets/laravel-blade/README.md
Normal file
149
my-snippets/laravel-blade/README.md
Normal file
|
@ -0,0 +1,149 @@
|
|||
# [Laravel Blade Snippets](https://marketplace.visualstudio.com/items?itemName=onecentlin.laravel-blade)
|
||||
|
||||
Laravel blade snippets and syntax highlight support for Visual Studio Code.
|
||||
|
||||
> Suggest Laravel related extension: [Laravel Snippets](https://marketplace.visualstudio.com/items?itemName=onecentlin.laravel5-snippets)
|
||||
|
||||
## Screenshot
|
||||
|
||||

|
||||
|
||||
## User Settings
|
||||
|
||||
Open `Preferences` -> `Settings`
|
||||
|
||||
```json
|
||||
"emmet.triggerExpansionOnTab": true, // enable tab to expanse emmet tags
|
||||
"blade.format.enable": true, // if you would like to enable blade format
|
||||
```
|
||||
|
||||
Specific settings for blade language
|
||||
|
||||
```json
|
||||
"[blade]": {
|
||||
"editor.autoClosingBrackets": "always"
|
||||
},
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- Blade syntax highlight
|
||||
- Blade snippets
|
||||
- Emmet works in blade template
|
||||
- Blade formatting
|
||||
|
||||
## Blade Syntax Hightlight
|
||||
|
||||
- Auto detected with `.blade.php` extension
|
||||
- Manually switch language mode to `Blade` (`Ctrl + K, M` or `⌘ + K, M`)
|
||||
|
||||
## Laravel Blade Snippets
|
||||
|
||||
| Trigger | Snippet |
|
||||
| ------------------- | ----------------------------------------- |
|
||||
| b:extends | @extends |
|
||||
| b:yield | @yield |
|
||||
| b:section | @section...@endsection |
|
||||
| b:section-show | @section...@show |
|
||||
| b:if | @if...@endif |
|
||||
| b:if-else | @if...@else...@endif |
|
||||
| b:unless | @unless...@endunless |
|
||||
| b:has-section | @hasSection...@else...@endif |
|
||||
| b:for | @for...@endfor |
|
||||
| b:foreach | @foreach...@endforeach |
|
||||
| b:forelse | @forelse...@empty...@endforelse |
|
||||
| b:while | @while...@endwhile |
|
||||
| b:each | @each |
|
||||
| b:push | @push...@endpush |
|
||||
| b:stack | @stack |
|
||||
| b:inject | @inject |
|
||||
| b:comment | {{-- comment --}} (`Ctrl + /` or `⌘ + /`) |
|
||||
| b:echo | {{ $data }} |
|
||||
| b:echo-html | {!! $html !!} |
|
||||
| b:echo-raw | @{{ variable }} |
|
||||
| b:can | @can...@endcan (v5.1) |
|
||||
| b:can-elsecan | @can...@elsecan...@endcan (v5.1) |
|
||||
| b:canany | @canany...@endcanany (v5.8) |
|
||||
| b:canany-elsecanany | @canany...@elsecanany...@endcanany (v5.8) |
|
||||
| b:cannot | @cannot...@endcannot (v5.3) |
|
||||
| b:cannot-elsecannot | @cannot...@elsecannot...@endcannot (v5.3) |
|
||||
| b:verbatim | @verbatim...@endverbatim (v5.3) |
|
||||
| b:php | @php...@endphp (v5.3) |
|
||||
| b:includeIf | @includeIf (v5.3) |
|
||||
| b:includeWhen | @includeWhen (v5.4) |
|
||||
| b:includeFirst | @includeFirst (v5.5) |
|
||||
| b:includeUnless | @includeUnless (v6.x) |
|
||||
| b:component | @component...@endcomponent (v5.4) |
|
||||
| b:slot | @slot...@endslot (v5.4) |
|
||||
| b:isset | @isset...@endisset (v5.4) |
|
||||
| b:empty | @empty...@endempty (v5.4) |
|
||||
| b:auth | @auth...@endauth (v5.5) |
|
||||
| b:guest | @guest...@endguest (v5.5) |
|
||||
| b:switch | @switch...@case...@endswitch (v5.5) |
|
||||
| b:lang | @lang |
|
||||
| b:csrf | @csrf (v5.6) |
|
||||
| b:method | @method(...) (v5.6) |
|
||||
| b:dump | @dump(...) (v5.6) |
|
||||
| b:error | @error...@enderror (v5.8) |
|
||||
| b:props | @props (v7.4) |
|
||||
| b:production | @production...@endproduction |
|
||||
| b:env | @env...@endenv |
|
||||
| b:once | @once...@endonce |
|
||||
| b:class | @class (v8.51) |
|
||||
| b:aware | @aware (v8.64) |
|
||||
| b:js | @js (v8.71) |
|
||||
| b:checked | @checked (v9.x) |
|
||||
| b:selected | @selected (v9.x) |
|
||||
| b:disabled | @disabled (v9.x) |
|
||||
|
||||
### $loop variable (Laravel v5.3+)
|
||||
|
||||
| Trigger | Snippet |
|
||||
| ------------ | ------------------------------------------------------ |
|
||||
| b:loop | $loop->(index,remaining,count,first,last,depth,parent) |
|
||||
| b:loop-first | @if($loop->first)...@endif |
|
||||
| b:loop-last | @if($loop->last)...@endif |
|
||||
|
||||
## Laravel Helper Snippets for Blade
|
||||
|
||||
| Trigger | Laravel Helper |
|
||||
| ------------------- | --------------------- |
|
||||
| lv:elixir | elixir() - deprecated |
|
||||
| lv:mix | mix() (v5.4) |
|
||||
| lv:trans | trans() |
|
||||
| lv:action | action() |
|
||||
| lv:secure-asset | secure_asset() |
|
||||
| lv:url | url() |
|
||||
| lv:asset | asset() |
|
||||
| lv:route | route() |
|
||||
| lv:csrf-field | csrf_field() |
|
||||
| lv:csrf-token | csrf_token() |
|
||||
| lv:pagination-links | $collection->links() |
|
||||
|
||||
## Blade extensions
|
||||
|
||||
Register in the `boot` method of `ServiceProvider`
|
||||
|
||||
- `Blade::component`
|
||||
- `Blade::include`
|
||||
- `Blade::if`
|
||||
- `Blade::directive`
|
||||
- `Blade::stringable`
|
||||
|
||||
Rendering inline blade templates
|
||||
|
||||
- `Blade::render`
|
||||
- `Blade::renderComponent`
|
||||
|
||||
## Contact
|
||||
|
||||
Please file any [issues](https://github.com/onecentlin/laravel-blade-snippets-vscode/issues) or have a suggestion please tweet me [@onecentlin](https://twitter.com/onecentlin).
|
||||
|
||||
## Credits
|
||||
|
||||
- Blade language grammar is based on [Medalink syntax definition](https://github.com/Medalink/laravel-blade) for Sublime Text; Converted from [Blade templating support in Atom](https://github.com/jawee/language-blade)
|
||||
- Textmate language format file is based on [Textmate bundle for Laravel 5](https://github.com/loranger/Laravel.tmbundle).
|
||||
|
||||
## License
|
||||
|
||||
Please read [License](https://github.com/onecentlin/laravel-blade-snippets-vscode/blob/master/LICENSE.md) for more information
|
24
my-snippets/laravel-blade/blade.configuration.json
Normal file
24
my-snippets/laravel-blade/blade.configuration.json
Normal file
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"comments": {
|
||||
"blockComment": [ "{{--", "--}}" ]
|
||||
},
|
||||
"brackets": [
|
||||
["{", "}"],
|
||||
["[", "]"],
|
||||
["(", ")"]
|
||||
],
|
||||
"autoClosingPairs": [
|
||||
["{", "}"],
|
||||
["[", "]"],
|
||||
["(", ")"],
|
||||
["\"", "\""],
|
||||
["'", "'"]
|
||||
],
|
||||
"surroundingPairs": [
|
||||
["{", "}"],
|
||||
["[", "]"],
|
||||
["(", ")"],
|
||||
["\"", "\""],
|
||||
["'", "'"]
|
||||
]
|
||||
}
|
BIN
my-snippets/laravel-blade/images/icon.png
Normal file
BIN
my-snippets/laravel-blade/images/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
BIN
my-snippets/laravel-blade/images/language-mode.png
Normal file
BIN
my-snippets/laravel-blade/images/language-mode.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
BIN
my-snippets/laravel-blade/images/screenshot.gif
Normal file
BIN
my-snippets/laravel-blade/images/screenshot.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 315 KiB |
BIN
my-snippets/laravel-blade/images/screenshots.png
Normal file
BIN
my-snippets/laravel-blade/images/screenshots.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 117 KiB |
8539
my-snippets/laravel-blade/package-lock.json
generated
Normal file
8539
my-snippets/laravel-blade/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
120
my-snippets/laravel-blade/package.json
Normal file
120
my-snippets/laravel-blade/package.json
Normal file
|
@ -0,0 +1,120 @@
|
|||
{
|
||||
"name": "laravel-blade",
|
||||
"displayName": "Laravel Blade Snippets",
|
||||
"description": "Laravel blade snippets and syntax highlight support",
|
||||
"version": "1.32.0",
|
||||
"publisher": "onecentlin",
|
||||
"author": {
|
||||
"name": "Winnie Lin",
|
||||
"email": "onecentlin@gmail.com",
|
||||
"url": "https://devmanna.blogspot.com"
|
||||
},
|
||||
"homepage": "https://github.com/onecentlin/laravel-blade-snippets-vscode",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/onecentlin/laravel-blade-snippets-vscode"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/onecentlin/laravel-blade-snippets-vscode/issues"
|
||||
},
|
||||
"engines": {
|
||||
"vscode": "^1.46.0"
|
||||
},
|
||||
"keywords": [
|
||||
"laravel",
|
||||
"blade",
|
||||
"template",
|
||||
"snippet",
|
||||
"formatter"
|
||||
],
|
||||
"icon": "images/icon.png",
|
||||
"galleryBanner": {
|
||||
"color": "#f66f62",
|
||||
"theme": "dark"
|
||||
},
|
||||
"categories": [
|
||||
"Programming Languages",
|
||||
"Snippets",
|
||||
"Formatters"
|
||||
],
|
||||
"main": "./out/extension.js",
|
||||
"scripts": {
|
||||
"build-srv": "cd ./server && npm install && tsc -p ./",
|
||||
"compile": "tsc -watch -p ./",
|
||||
"vscode:prepublish": "webpack --mode production && pushd \"./\" && npm run build-srv && popd",
|
||||
"webpack": "webpack --mode development",
|
||||
"webpack-dev": "webpack --mode development --watch"
|
||||
},
|
||||
"contributes": {
|
||||
"languages": [
|
||||
{
|
||||
"id": "blade",
|
||||
"aliases": [
|
||||
"Blade",
|
||||
"blade"
|
||||
],
|
||||
"extensions": [
|
||||
".blade.php"
|
||||
],
|
||||
"configuration": "./blade.configuration.json"
|
||||
}
|
||||
],
|
||||
"grammars": [
|
||||
{
|
||||
"language": "blade",
|
||||
"scopeName": "text.html.php.blade",
|
||||
"path": "./syntaxes/blade.tmLanguage.json",
|
||||
"embeddedLanguages": {
|
||||
"source.php": "php",
|
||||
"source.css": "css",
|
||||
"source.js": "javascript"
|
||||
}
|
||||
}
|
||||
],
|
||||
"snippets": [
|
||||
{
|
||||
"language": "blade",
|
||||
"path": "./snippets/snippets.json"
|
||||
},
|
||||
{
|
||||
"language": "blade",
|
||||
"path": "./snippets/helpers.json"
|
||||
},
|
||||
{
|
||||
"language": "blade",
|
||||
"path": "./snippets/livewire.json"
|
||||
},
|
||||
{
|
||||
"language": "php",
|
||||
"path": "./snippets/blade.json"
|
||||
}
|
||||
],
|
||||
"configuration": {
|
||||
"title": "Blade Configuration",
|
||||
"properties": {
|
||||
"blade.format.enable": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Enable format blade file"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"activationEvents": [
|
||||
"onLanguage:blade"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.0.0",
|
||||
"@types/vscode": "^1.46.0",
|
||||
"ts-loader": "^7.0.5",
|
||||
"typescript": "^3.9.5",
|
||||
"webpack": "^4.43.0",
|
||||
"webpack-cli": "^4.9.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"vscode-css-languageservice": "^5.1.7",
|
||||
"vscode-html-languageservice": "^4.1.0",
|
||||
"vscode-languageclient": "^6.1.3",
|
||||
"vscode-languageserver-types": "^3.16.0"
|
||||
}
|
||||
}
|
6
my-snippets/laravel-blade/server/lib/OSSREADME.json
Normal file
6
my-snippets/laravel-blade/server/lib/OSSREADME.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
// ATTENTION - THIS DIRECTORY CONTAINS THIRD PARTY OPEN SOURCE MATERIALS:
|
||||
[{
|
||||
"name": "definitelytyped",
|
||||
"repositoryURL": "https://github.com/DefinitelyTyped/DefinitelyTyped",
|
||||
"license": "MIT"
|
||||
}]
|
3759
my-snippets/laravel-blade/server/lib/jquery.d.ts
vendored
Normal file
3759
my-snippets/laravel-blade/server/lib/jquery.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load diff
300
my-snippets/laravel-blade/server/package-lock.json
generated
Normal file
300
my-snippets/laravel-blade/server/package-lock.json
generated
Normal file
|
@ -0,0 +1,300 @@
|
|||
{
|
||||
"name": "vscode-html-languageserver",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "vscode-html-languageserver",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"typescript": "^2.7.1",
|
||||
"vscode-css-languageservice": "^4.0.2",
|
||||
"vscode-emmet-helper": "^1.2.15",
|
||||
"vscode-html-languageservice": "^3.0.2",
|
||||
"vscode-languageserver": "^4.0.0-next.4",
|
||||
"vscode-languageserver-types": "^3.14.0",
|
||||
"vscode-nls": "^4.1.1",
|
||||
"vscode-uri": "^1.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mocha": "2.2.33",
|
||||
"@types/node": "7.0.43"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@emmetio/extract-abbreviation": {
|
||||
"version": "0.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@emmetio/extract-abbreviation/-/extract-abbreviation-0.1.6.tgz",
|
||||
"integrity": "sha512-Ce3xE2JvTSEbASFbRbA1gAIcMcZWdS2yUYRaQbeM0nbOzaZrUYfa3ePtcriYRZOZmr+CkKA+zbjhvTpIOAYVcw=="
|
||||
},
|
||||
"node_modules/@types/mocha": {
|
||||
"version": "2.2.33",
|
||||
"resolved": "http://registry.npm.taobao.org/@types/mocha/download/@types/mocha-2.2.33.tgz",
|
||||
"integrity": "sha1-15oAYewnA3n02eIl9AlvtDZmne8=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "7.0.43",
|
||||
"resolved": "http://registry.npm.taobao.org/@types/node/download/@types/node-7.0.43.tgz",
|
||||
"integrity": "sha1-oYfghJWgdfIAypRgeckU4aX+liw=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/jsonc-parser": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-1.0.3.tgz",
|
||||
"integrity": "sha512-hk/69oAeaIzchq/v3lS50PXuzn5O2ynldopMC+SWBql7J2WtdptfB9dy8Y7+Og5rPkTCpn83zTiO8FMcqlXJ/g=="
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-2.7.1.tgz",
|
||||
"integrity": "sha512-bqB1yS6o9TNA9ZC/MJxM0FZzPnZdtHj0xWK/IZ5khzVqdpGul/R/EIiHRgFXlwTD7PSIaYVnGKq1QgMCu2mnqw==",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-css-languageservice": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-4.0.2.tgz",
|
||||
"integrity": "sha512-pTnfXbsME3pl+yDfhUp/mtvPyIJk0Le4zqJxDn56s9GY9LqY0RmkSEh0oHH6D0HXR3Ni6wKosIaqu8a2G0+jdw==",
|
||||
"dependencies": {
|
||||
"vscode-languageserver-types": "^3.15.0-next.2",
|
||||
"vscode-nls": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-css-languageservice/node_modules/vscode-languageserver-types": {
|
||||
"version": "3.15.0-next.2",
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.2.tgz",
|
||||
"integrity": "sha512-2JkrMWWUi2rlVLSo9OFR2PIGUzdiowEM8NgNYiwLKnXTjpwpjjIrJbNNxDik7Rv4oo9KtikcFQZKXbrKilL/MQ=="
|
||||
},
|
||||
"node_modules/vscode-css-languageservice/node_modules/vscode-nls": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.1.tgz",
|
||||
"integrity": "sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A=="
|
||||
},
|
||||
"node_modules/vscode-emmet-helper": {
|
||||
"version": "1.2.15",
|
||||
"resolved": "https://registry.npmjs.org/vscode-emmet-helper/-/vscode-emmet-helper-1.2.15.tgz",
|
||||
"integrity": "sha512-JplvmMMWSvm/6/dZezix2ADPM49u6YahPYjs/QToohUpomW/2Eb27ecCrkCyOGBPfKLKGiOPHCssss8TSDA9ag==",
|
||||
"deprecated": "This package has been renamed to @vscode/emmet-helper, please update to the new name",
|
||||
"dependencies": {
|
||||
"@emmetio/extract-abbreviation": "0.1.6",
|
||||
"jsonc-parser": "^1.0.0",
|
||||
"vscode-languageserver-types": "^3.6.0-next.1"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-html-languageservice": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-3.0.2.tgz",
|
||||
"integrity": "sha512-MP9al7nk1SqQwW4GdDy6Ec3UU1GKy0Wf4pzo3nQ5lgdScb2pajV7iyXZIGJk7jQbifkZWnG0jB7CKecTNFynJw==",
|
||||
"dependencies": {
|
||||
"vscode-languageserver-types": "^3.15.0-next.2",
|
||||
"vscode-nls": "^4.1.1",
|
||||
"vscode-uri": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-html-languageservice/node_modules/vscode-languageserver-types": {
|
||||
"version": "3.15.0-next.2",
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.2.tgz",
|
||||
"integrity": "sha512-2JkrMWWUi2rlVLSo9OFR2PIGUzdiowEM8NgNYiwLKnXTjpwpjjIrJbNNxDik7Rv4oo9KtikcFQZKXbrKilL/MQ=="
|
||||
},
|
||||
"node_modules/vscode-html-languageservice/node_modules/vscode-nls": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.1.tgz",
|
||||
"integrity": "sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A=="
|
||||
},
|
||||
"node_modules/vscode-html-languageservice/node_modules/vscode-uri": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.0.3.tgz",
|
||||
"integrity": "sha512-4D3DI3F4uRy09WNtDGD93H9q034OHImxiIcSq664Hq1Y1AScehlP3qqZyTkX/RWxeu0MRMHGkrxYqm2qlDF/aw=="
|
||||
},
|
||||
"node_modules/vscode-jsonrpc": {
|
||||
"version": "3.6.0-next.1",
|
||||
"resolved": "http://registry.npm.taobao.org/vscode-jsonrpc/download/vscode-jsonrpc-3.6.0-next.1.tgz",
|
||||
"integrity": "sha1-PLRj3/5YQtauwWcYypJScIzWqr4=",
|
||||
"engines": {
|
||||
"node": ">=4.0.0 || >=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-languageserver": {
|
||||
"version": "4.0.0-next.4",
|
||||
"resolved": "http://registry.npm.taobao.org/vscode-languageserver/download/vscode-languageserver-4.0.0-next.4.tgz",
|
||||
"integrity": "sha1-FiRAsVvtqrB+FnbwRuTZuFeLPZI=",
|
||||
"dependencies": {
|
||||
"vscode-languageserver-protocol": "^3.6.0-next.5",
|
||||
"vscode-uri": "^1.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"installServerIntoExtension": "bin/installServerIntoExtension"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-languageserver-protocol": {
|
||||
"version": "3.6.0-next.5",
|
||||
"resolved": "http://registry.npm.taobao.org/vscode-languageserver-protocol/download/vscode-languageserver-protocol-3.6.0-next.5.tgz",
|
||||
"integrity": "sha1-7S7C23WYJvdTwKE5d9+yvtxNMbM=",
|
||||
"dependencies": {
|
||||
"vscode-jsonrpc": "^3.6.0-next.1",
|
||||
"vscode-languageserver-types": "^3.6.0-next.1"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-languageserver-types": {
|
||||
"version": "3.14.0",
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz",
|
||||
"integrity": "sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A=="
|
||||
},
|
||||
"node_modules/vscode-languageserver/node_modules/vscode-uri": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.8.tgz",
|
||||
"integrity": "sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ=="
|
||||
},
|
||||
"node_modules/vscode-nls": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.1.tgz",
|
||||
"integrity": "sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A=="
|
||||
},
|
||||
"node_modules/vscode-uri": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.8.tgz",
|
||||
"integrity": "sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ=="
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@emmetio/extract-abbreviation": {
|
||||
"version": "0.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@emmetio/extract-abbreviation/-/extract-abbreviation-0.1.6.tgz",
|
||||
"integrity": "sha512-Ce3xE2JvTSEbASFbRbA1gAIcMcZWdS2yUYRaQbeM0nbOzaZrUYfa3ePtcriYRZOZmr+CkKA+zbjhvTpIOAYVcw=="
|
||||
},
|
||||
"@types/mocha": {
|
||||
"version": "2.2.33",
|
||||
"resolved": "http://registry.npm.taobao.org/@types/mocha/download/@types/mocha-2.2.33.tgz",
|
||||
"integrity": "sha1-15oAYewnA3n02eIl9AlvtDZmne8=",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "7.0.43",
|
||||
"resolved": "http://registry.npm.taobao.org/@types/node/download/@types/node-7.0.43.tgz",
|
||||
"integrity": "sha1-oYfghJWgdfIAypRgeckU4aX+liw=",
|
||||
"dev": true
|
||||
},
|
||||
"jsonc-parser": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-1.0.3.tgz",
|
||||
"integrity": "sha512-hk/69oAeaIzchq/v3lS50PXuzn5O2ynldopMC+SWBql7J2WtdptfB9dy8Y7+Og5rPkTCpn83zTiO8FMcqlXJ/g=="
|
||||
},
|
||||
"typescript": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-2.7.1.tgz",
|
||||
"integrity": "sha512-bqB1yS6o9TNA9ZC/MJxM0FZzPnZdtHj0xWK/IZ5khzVqdpGul/R/EIiHRgFXlwTD7PSIaYVnGKq1QgMCu2mnqw=="
|
||||
},
|
||||
"vscode-css-languageservice": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-4.0.2.tgz",
|
||||
"integrity": "sha512-pTnfXbsME3pl+yDfhUp/mtvPyIJk0Le4zqJxDn56s9GY9LqY0RmkSEh0oHH6D0HXR3Ni6wKosIaqu8a2G0+jdw==",
|
||||
"requires": {
|
||||
"vscode-languageserver-types": "^3.15.0-next.2",
|
||||
"vscode-nls": "^4.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"vscode-languageserver-types": {
|
||||
"version": "3.15.0-next.2",
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.2.tgz",
|
||||
"integrity": "sha512-2JkrMWWUi2rlVLSo9OFR2PIGUzdiowEM8NgNYiwLKnXTjpwpjjIrJbNNxDik7Rv4oo9KtikcFQZKXbrKilL/MQ=="
|
||||
},
|
||||
"vscode-nls": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.1.tgz",
|
||||
"integrity": "sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"vscode-emmet-helper": {
|
||||
"version": "1.2.15",
|
||||
"resolved": "https://registry.npmjs.org/vscode-emmet-helper/-/vscode-emmet-helper-1.2.15.tgz",
|
||||
"integrity": "sha512-JplvmMMWSvm/6/dZezix2ADPM49u6YahPYjs/QToohUpomW/2Eb27ecCrkCyOGBPfKLKGiOPHCssss8TSDA9ag==",
|
||||
"requires": {
|
||||
"@emmetio/extract-abbreviation": "0.1.6",
|
||||
"jsonc-parser": "^1.0.0",
|
||||
"vscode-languageserver-types": "^3.6.0-next.1"
|
||||
}
|
||||
},
|
||||
"vscode-html-languageservice": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-3.0.2.tgz",
|
||||
"integrity": "sha512-MP9al7nk1SqQwW4GdDy6Ec3UU1GKy0Wf4pzo3nQ5lgdScb2pajV7iyXZIGJk7jQbifkZWnG0jB7CKecTNFynJw==",
|
||||
"requires": {
|
||||
"vscode-languageserver-types": "^3.15.0-next.2",
|
||||
"vscode-nls": "^4.1.1",
|
||||
"vscode-uri": "^2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"vscode-languageserver-types": {
|
||||
"version": "3.15.0-next.2",
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.2.tgz",
|
||||
"integrity": "sha512-2JkrMWWUi2rlVLSo9OFR2PIGUzdiowEM8NgNYiwLKnXTjpwpjjIrJbNNxDik7Rv4oo9KtikcFQZKXbrKilL/MQ=="
|
||||
},
|
||||
"vscode-nls": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.1.tgz",
|
||||
"integrity": "sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A=="
|
||||
},
|
||||
"vscode-uri": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.0.3.tgz",
|
||||
"integrity": "sha512-4D3DI3F4uRy09WNtDGD93H9q034OHImxiIcSq664Hq1Y1AScehlP3qqZyTkX/RWxeu0MRMHGkrxYqm2qlDF/aw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"vscode-jsonrpc": {
|
||||
"version": "3.6.0-next.1",
|
||||
"resolved": "http://registry.npm.taobao.org/vscode-jsonrpc/download/vscode-jsonrpc-3.6.0-next.1.tgz",
|
||||
"integrity": "sha1-PLRj3/5YQtauwWcYypJScIzWqr4="
|
||||
},
|
||||
"vscode-languageserver": {
|
||||
"version": "4.0.0-next.4",
|
||||
"resolved": "http://registry.npm.taobao.org/vscode-languageserver/download/vscode-languageserver-4.0.0-next.4.tgz",
|
||||
"integrity": "sha1-FiRAsVvtqrB+FnbwRuTZuFeLPZI=",
|
||||
"requires": {
|
||||
"vscode-languageserver-protocol": "^3.6.0-next.5",
|
||||
"vscode-uri": "^1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"vscode-uri": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.8.tgz",
|
||||
"integrity": "sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"vscode-languageserver-protocol": {
|
||||
"version": "3.6.0-next.5",
|
||||
"resolved": "http://registry.npm.taobao.org/vscode-languageserver-protocol/download/vscode-languageserver-protocol-3.6.0-next.5.tgz",
|
||||
"integrity": "sha1-7S7C23WYJvdTwKE5d9+yvtxNMbM=",
|
||||
"requires": {
|
||||
"vscode-jsonrpc": "^3.6.0-next.1",
|
||||
"vscode-languageserver-types": "^3.6.0-next.1"
|
||||
}
|
||||
},
|
||||
"vscode-languageserver-types": {
|
||||
"version": "3.14.0",
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz",
|
||||
"integrity": "sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A=="
|
||||
},
|
||||
"vscode-nls": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.1.tgz",
|
||||
"integrity": "sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A=="
|
||||
},
|
||||
"vscode-uri": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.8.tgz",
|
||||
"integrity": "sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ=="
|
||||
}
|
||||
}
|
||||
}
|
32
my-snippets/laravel-blade/server/package.json
Normal file
32
my-snippets/laravel-blade/server/package.json
Normal file
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"name": "vscode-html-languageserver",
|
||||
"description": "HTML language server",
|
||||
"version": "1.0.0",
|
||||
"author": "Microsoft Corporation",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"dependencies": {
|
||||
"typescript": "^2.7.1",
|
||||
"vscode-css-languageservice": "^4.0.2",
|
||||
"vscode-html-languageservice": "^3.0.2",
|
||||
"vscode-emmet-helper": "^1.2.15",
|
||||
"vscode-languageserver": "^4.0.0-next.4",
|
||||
"vscode-languageserver-types": "^3.14.0",
|
||||
"vscode-nls": "^4.1.1",
|
||||
"vscode-uri": "^1.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mocha": "2.2.33",
|
||||
"@types/node": "7.0.43"
|
||||
},
|
||||
"scripts": {
|
||||
"compile": "gulp compile-extension:html-server",
|
||||
"watch": "gulp watch-extension:html-server",
|
||||
"install-service-next": "yarn add vscode-css-languageservice@next && yarn add vscode-html-languageservice@next",
|
||||
"install-service-local": "npm install ../../../../vscode-css-languageservice -f && npm install ../../../../vscode-html-languageservice -f",
|
||||
"install-server-next": "yarn add vscode-languageserver@next",
|
||||
"install-server-local": "npm install ../../../../vscode-languageserver-node/server -f"
|
||||
}
|
||||
}
|
452
my-snippets/laravel-blade/server/src/htmlServerMain.ts
Normal file
452
my-snippets/laravel-blade/server/src/htmlServerMain.ts
Normal file
|
@ -0,0 +1,452 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { createConnection, IConnection, TextDocuments, InitializeParams, InitializeResult, RequestType, DocumentRangeFormattingRequest, Disposable, DocumentSelector, TextDocumentPositionParams, ServerCapabilities, Position, CompletionTriggerKind } from 'vscode-languageserver';
|
||||
import { TextDocument, Diagnostic, DocumentLink, SymbolInformation, CompletionList } from 'vscode-languageserver-types';
|
||||
import { getLanguageModes, LanguageModes, Settings } from './modes/languageModes';
|
||||
|
||||
import { ConfigurationRequest, ConfigurationParams } from 'vscode-languageserver-protocol/lib/protocol.configuration.proposed';
|
||||
import { DocumentColorRequest, ServerCapabilities as CPServerCapabilities, ColorInformation, ColorPresentationRequest } from 'vscode-languageserver-protocol/lib/protocol.colorProvider.proposed';
|
||||
import { DidChangeWorkspaceFoldersNotification, WorkspaceFolder } from 'vscode-languageserver-protocol/lib/protocol.workspaceFolders.proposed';
|
||||
|
||||
import { format } from './modes/formatting';
|
||||
import { pushAll } from './utils/arrays';
|
||||
import { getDocumentContext } from './utils/documentContext';
|
||||
import uri from 'vscode-uri';
|
||||
import { formatError, runSafe } from './utils/errors';
|
||||
import { doComplete as emmetDoComplete, updateExtensionsPath as updateEmmetExtensionsPath, getEmmetCompletionParticipants } from 'vscode-emmet-helper';
|
||||
|
||||
namespace TagCloseRequest {
|
||||
export const type: RequestType<TextDocumentPositionParams, string | null, any, any> = new RequestType('html/tag');
|
||||
}
|
||||
|
||||
// Create a connection for the server
|
||||
let connection: IConnection = createConnection();
|
||||
|
||||
console.log = connection.console.log.bind(connection.console);
|
||||
console.error = connection.console.error.bind(connection.console);
|
||||
|
||||
process.on('unhandledRejection', (e: any) => {
|
||||
connection.console.error(formatError(`Unhandled exception`, e));
|
||||
});
|
||||
|
||||
// Create a simple text document manager. The text document manager
|
||||
// supports full document sync only
|
||||
let documents: TextDocuments = new TextDocuments();
|
||||
// Make the text document manager listen on the connection
|
||||
// for open, change and close text document events
|
||||
documents.listen(connection);
|
||||
|
||||
let workspaceFolders: WorkspaceFolder[] | undefined;
|
||||
|
||||
var languageModes: LanguageModes;
|
||||
|
||||
let clientSnippetSupport = false;
|
||||
let clientDynamicRegisterSupport = false;
|
||||
let scopedSettingsSupport = false;
|
||||
let workspaceFoldersSupport = false;
|
||||
|
||||
var globalSettings: Settings = {};
|
||||
let documentSettings: { [key: string]: Thenable<Settings> } = {};
|
||||
// remove document settings on close
|
||||
documents.onDidClose(e => {
|
||||
delete documentSettings[e.document.uri];
|
||||
});
|
||||
|
||||
function getDocumentSettings(textDocument: TextDocument, needsDocumentSettings: () => boolean): Thenable<Settings | undefined> {
|
||||
if (scopedSettingsSupport && needsDocumentSettings()) {
|
||||
let promise = documentSettings[textDocument.uri];
|
||||
if (!promise) {
|
||||
let scopeUri = textDocument.uri;
|
||||
let configRequestParam: ConfigurationParams = { items: [{ scopeUri, section: 'css' }, { scopeUri, section: 'html' }, { scopeUri, section: 'javascript' }] };
|
||||
promise = connection.sendRequest(ConfigurationRequest.type, configRequestParam).then(s => ({ css: s[0], html: s[1], javascript: s[2] }));
|
||||
documentSettings[textDocument.uri] = promise;
|
||||
}
|
||||
return promise;
|
||||
}
|
||||
return Promise.resolve(void 0);
|
||||
}
|
||||
|
||||
let emmetSettings = {};
|
||||
let currentEmmetExtensionsPath: string;
|
||||
const emmetTriggerCharacters = ['!', '.', '}', ':', '*', '$', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
|
||||
|
||||
// After the server has started the client sends an initilize request. The server receives
|
||||
// in the passed params the rootPath of the workspace plus the client capabilites
|
||||
connection.onInitialize((params: InitializeParams): InitializeResult => {
|
||||
let initializationOptions = params.initializationOptions;
|
||||
|
||||
workspaceFolders = (<any>params).workspaceFolders;
|
||||
if (!Array.isArray(workspaceFolders)) {
|
||||
workspaceFolders = [];
|
||||
if (params.rootPath) {
|
||||
workspaceFolders.push({ name: '', uri: uri.file(params.rootPath).toString() });
|
||||
}
|
||||
}
|
||||
|
||||
languageModes = getLanguageModes(initializationOptions ? initializationOptions.embeddedLanguages : { css: true, javascript: true });
|
||||
documents.onDidClose(e => {
|
||||
languageModes.onDocumentRemoved(e.document);
|
||||
});
|
||||
connection.onShutdown(() => {
|
||||
languageModes.dispose();
|
||||
});
|
||||
|
||||
function hasClientCapability(...keys: string[]) {
|
||||
let c = <any>params.capabilities;
|
||||
for (let i = 0; c && i < keys.length; i++) {
|
||||
c = c[keys[i]];
|
||||
}
|
||||
return !!c;
|
||||
}
|
||||
|
||||
clientSnippetSupport = hasClientCapability('textDocument', 'completion', 'completionItem', 'snippetSupport');
|
||||
clientDynamicRegisterSupport = hasClientCapability('workspace', 'symbol', 'dynamicRegistration');
|
||||
scopedSettingsSupport = hasClientCapability('workspace', 'configuration');
|
||||
workspaceFoldersSupport = hasClientCapability('workspace', 'workspaceFolders');
|
||||
let capabilities: ServerCapabilities & CPServerCapabilities = {
|
||||
// Tell the client that the server works in FULL text document sync mode
|
||||
textDocumentSync: documents.syncKind,
|
||||
completionProvider: clientSnippetSupport ? { resolveProvider: true, triggerCharacters: [...emmetTriggerCharacters, '.', ':', '<', '"', '=', '/'] } : undefined,
|
||||
hoverProvider: true,
|
||||
documentHighlightProvider: true,
|
||||
documentRangeFormattingProvider: false,
|
||||
documentSymbolProvider: true,
|
||||
definitionProvider: true,
|
||||
signatureHelpProvider: { triggerCharacters: ['('] },
|
||||
referencesProvider: true,
|
||||
colorProvider: true
|
||||
};
|
||||
return { capabilities };
|
||||
});
|
||||
|
||||
connection.onInitialized((p) => {
|
||||
if (workspaceFoldersSupport) {
|
||||
connection.client.register(DidChangeWorkspaceFoldersNotification.type);
|
||||
|
||||
connection.onNotification(DidChangeWorkspaceFoldersNotification.type, e => {
|
||||
let toAdd = e.event.added;
|
||||
let toRemove = e.event.removed;
|
||||
let updatedFolders = [];
|
||||
if (workspaceFolders) {
|
||||
for (let folder of workspaceFolders) {
|
||||
if (!toRemove.some(r => r.uri === folder.uri) && !toAdd.some(r => r.uri === folder.uri)) {
|
||||
updatedFolders.push(folder);
|
||||
}
|
||||
}
|
||||
}
|
||||
workspaceFolders = updatedFolders.concat(toAdd);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
let formatterRegistration: Thenable<Disposable> | null = null;
|
||||
|
||||
// The settings have changed. Is send on server activation as well.
|
||||
connection.onDidChangeConfiguration((change) => {
|
||||
globalSettings = change.settings;
|
||||
|
||||
documentSettings = {}; // reset all document settings
|
||||
languageModes.getAllModes().forEach(m => {
|
||||
if (m.configure) {
|
||||
m.configure(change.settings);
|
||||
}
|
||||
});
|
||||
documents.all().forEach(triggerValidation);
|
||||
|
||||
// dynamically enable & disable the formatter
|
||||
if (clientDynamicRegisterSupport) {
|
||||
let enableFormatter = globalSettings && globalSettings.html && globalSettings.html.format && globalSettings.html.format.enable;
|
||||
if (enableFormatter) {
|
||||
if (!formatterRegistration) {
|
||||
let documentSelector: DocumentSelector = [{ language: 'html' }, { language: 'handlebars' }]; // don't register razor, the formatter does more harm than good
|
||||
formatterRegistration = connection.client.register(DocumentRangeFormattingRequest.type, { documentSelector });
|
||||
}
|
||||
} else if (formatterRegistration) {
|
||||
formatterRegistration.then(r => r.dispose());
|
||||
formatterRegistration = null;
|
||||
}
|
||||
}
|
||||
|
||||
emmetSettings = globalSettings.emmet;
|
||||
if (currentEmmetExtensionsPath !== emmetSettings['extensionsPath']) {
|
||||
currentEmmetExtensionsPath = emmetSettings['extensionsPath'];
|
||||
const workspaceUri = (workspaceFolders && workspaceFolders.length === 1) ? uri.parse(workspaceFolders[0].uri) : null;
|
||||
updateEmmetExtensionsPath(currentEmmetExtensionsPath, workspaceUri ? workspaceUri.fsPath : null);
|
||||
}
|
||||
});
|
||||
|
||||
let pendingValidationRequests: { [uri: string]: NodeJS.Timer } = {};
|
||||
const validationDelayMs = 500;
|
||||
|
||||
// The content of a text document has changed. This event is emitted
|
||||
// when the text document first opened or when its content has changed.
|
||||
documents.onDidChangeContent(change => {
|
||||
triggerValidation(change.document);
|
||||
});
|
||||
|
||||
// a document has closed: clear all diagnostics
|
||||
documents.onDidClose(event => {
|
||||
cleanPendingValidation(event.document);
|
||||
connection.sendDiagnostics({ uri: event.document.uri, diagnostics: [] });
|
||||
});
|
||||
|
||||
function cleanPendingValidation(textDocument: TextDocument): void {
|
||||
let request = pendingValidationRequests[textDocument.uri];
|
||||
if (request) {
|
||||
clearTimeout(request);
|
||||
delete pendingValidationRequests[textDocument.uri];
|
||||
}
|
||||
}
|
||||
|
||||
function triggerValidation(textDocument: TextDocument): void {
|
||||
cleanPendingValidation(textDocument);
|
||||
pendingValidationRequests[textDocument.uri] = setTimeout(() => {
|
||||
delete pendingValidationRequests[textDocument.uri];
|
||||
validateTextDocument(textDocument);
|
||||
}, validationDelayMs);
|
||||
}
|
||||
|
||||
function isValidationEnabled(languageId: string, settings: Settings = globalSettings) {
|
||||
let validationSettings = settings && settings.html && settings.html.validate;
|
||||
if (validationSettings) {
|
||||
return languageId === 'css' && validationSettings.styles !== false || languageId === 'javascript' && validationSettings.scripts !== false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
async function validateTextDocument(textDocument: TextDocument) {
|
||||
try {
|
||||
let diagnostics: Diagnostic[] = [];
|
||||
if (textDocument.languageId === 'html') {
|
||||
let modes = languageModes.getAllModesInDocument(textDocument);
|
||||
let settings = await getDocumentSettings(textDocument, () => modes.some(m => !!m.doValidation));
|
||||
modes.forEach(mode => {
|
||||
if (mode.doValidation && isValidationEnabled(mode.getId(), settings)) {
|
||||
pushAll(diagnostics, mode.doValidation(textDocument, settings));
|
||||
}
|
||||
});
|
||||
}
|
||||
connection.sendDiagnostics({ uri: textDocument.uri, diagnostics });
|
||||
} catch (e) {
|
||||
connection.console.error(formatError(`Error while validating ${textDocument.uri}`, e));
|
||||
}
|
||||
}
|
||||
|
||||
let cachedCompletionList: CompletionList;
|
||||
const hexColorRegex = /^#[\d,a-f,A-F]{1,6}$/;
|
||||
connection.onCompletion(async textDocumentPosition => {
|
||||
return runSafe(async () => {
|
||||
let document = documents.get(textDocumentPosition.textDocument.uri);
|
||||
let mode = languageModes.getModeAtPosition(document, textDocumentPosition.position);
|
||||
if (!mode || !mode.doComplete) {
|
||||
return { isIncomplete: true, items: [] };
|
||||
}
|
||||
|
||||
if (cachedCompletionList
|
||||
&& !cachedCompletionList.isIncomplete
|
||||
&& (mode.getId() === 'html' || mode.getId() === 'css')
|
||||
&& textDocumentPosition.context
|
||||
&& textDocumentPosition.context.triggerKind === CompletionTriggerKind.TriggerForIncompleteCompletions
|
||||
) {
|
||||
let result: CompletionList = emmetDoComplete(document, textDocumentPosition.position, mode.getId(), emmetSettings);
|
||||
if (result && result.items) {
|
||||
result.items.push(...cachedCompletionList.items);
|
||||
} else {
|
||||
result = cachedCompletionList;
|
||||
cachedCompletionList = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (mode.getId() !== 'html') {
|
||||
connection.telemetry.logEvent({ key: 'html.embbedded.complete', value: { languageId: mode.getId() } });
|
||||
}
|
||||
|
||||
cachedCompletionList = null;
|
||||
let emmetCompletionList: CompletionList = {
|
||||
isIncomplete: true,
|
||||
items: undefined
|
||||
};
|
||||
if (mode.setCompletionParticipants) {
|
||||
const emmetCompletionParticipant = getEmmetCompletionParticipants(document, textDocumentPosition.position, mode.getId(), emmetSettings, emmetCompletionList);
|
||||
mode.setCompletionParticipants([emmetCompletionParticipant]);
|
||||
}
|
||||
|
||||
let settings = await getDocumentSettings(document, () => mode.doComplete.length > 2);
|
||||
let result = mode.doComplete(document, textDocumentPosition.position, settings);
|
||||
if (emmetCompletionList && emmetCompletionList.items) {
|
||||
cachedCompletionList = result;
|
||||
if (emmetCompletionList.items.length && hexColorRegex.test(emmetCompletionList.items[0].label) && result.items.some(x => x.label === emmetCompletionList.items[0].label)) {
|
||||
emmetCompletionList.items.shift();
|
||||
}
|
||||
return { isIncomplete: true, items: [...emmetCompletionList.items, ...result.items] };
|
||||
}
|
||||
return result;
|
||||
}, null, `Error while computing completions for ${textDocumentPosition.textDocument.uri}`);
|
||||
});
|
||||
|
||||
connection.onCompletionResolve(item => {
|
||||
return runSafe(() => {
|
||||
let data = item.data;
|
||||
if (data && data.languageId && data.uri) {
|
||||
let mode = languageModes.getMode(data.languageId);
|
||||
let document = documents.get(data.uri);
|
||||
if (mode && mode.doResolve && document) {
|
||||
return mode.doResolve(document, item);
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}, null, `Error while resolving completion proposal`);
|
||||
});
|
||||
|
||||
connection.onHover(textDocumentPosition => {
|
||||
return runSafe(() => {
|
||||
let document = documents.get(textDocumentPosition.textDocument.uri);
|
||||
let mode = languageModes.getModeAtPosition(document, textDocumentPosition.position);
|
||||
if (mode && mode.doHover) {
|
||||
return mode.doHover(document, textDocumentPosition.position);
|
||||
}
|
||||
return null;
|
||||
}, null, `Error while computing hover for ${textDocumentPosition.textDocument.uri}`);
|
||||
});
|
||||
|
||||
connection.onDocumentHighlight(documentHighlightParams => {
|
||||
return runSafe(() => {
|
||||
let document = documents.get(documentHighlightParams.textDocument.uri);
|
||||
let mode = languageModes.getModeAtPosition(document, documentHighlightParams.position);
|
||||
if (mode && mode.findDocumentHighlight) {
|
||||
return mode.findDocumentHighlight(document, documentHighlightParams.position);
|
||||
}
|
||||
return [];
|
||||
}, [], `Error while computing document highlights for ${documentHighlightParams.textDocument.uri}`);
|
||||
});
|
||||
|
||||
connection.onDefinition(definitionParams => {
|
||||
return runSafe(() => {
|
||||
let document = documents.get(definitionParams.textDocument.uri);
|
||||
let mode = languageModes.getModeAtPosition(document, definitionParams.position);
|
||||
if (mode && mode.findDefinition) {
|
||||
return mode.findDefinition(document, definitionParams.position);
|
||||
}
|
||||
return [];
|
||||
}, null, `Error while computing definitions for ${definitionParams.textDocument.uri}`);
|
||||
});
|
||||
|
||||
connection.onReferences(referenceParams => {
|
||||
return runSafe(() => {
|
||||
let document = documents.get(referenceParams.textDocument.uri);
|
||||
let mode = languageModes.getModeAtPosition(document, referenceParams.position);
|
||||
if (mode && mode.findReferences) {
|
||||
return mode.findReferences(document, referenceParams.position);
|
||||
}
|
||||
return [];
|
||||
}, [], `Error while computing references for ${referenceParams.textDocument.uri}`);
|
||||
});
|
||||
|
||||
connection.onSignatureHelp(signatureHelpParms => {
|
||||
return runSafe(() => {
|
||||
let document = documents.get(signatureHelpParms.textDocument.uri);
|
||||
let mode = languageModes.getModeAtPosition(document, signatureHelpParms.position);
|
||||
if (mode && mode.doSignatureHelp) {
|
||||
return mode.doSignatureHelp(document, signatureHelpParms.position);
|
||||
}
|
||||
return null;
|
||||
}, null, `Error while computing signature help for ${signatureHelpParms.textDocument.uri}`);
|
||||
});
|
||||
|
||||
connection.onDocumentRangeFormatting(async formatParams => {
|
||||
return runSafe(async () => {
|
||||
let document = documents.get(formatParams.textDocument.uri);
|
||||
let settings = await getDocumentSettings(document, () => true);
|
||||
if (!settings) {
|
||||
settings = globalSettings;
|
||||
}
|
||||
let unformattedTags: string = settings && settings.html && settings.html.format && settings.html.format.unformatted || '';
|
||||
let enabledModes = { css: !unformattedTags.match(/\bstyle\b/), javascript: !unformattedTags.match(/\bscript\b/) };
|
||||
|
||||
return format(languageModes, document, formatParams.range, formatParams.options, settings, enabledModes);
|
||||
}, [], `Error while formatting range for ${formatParams.textDocument.uri}`);
|
||||
});
|
||||
|
||||
connection.onDocumentLinks(documentLinkParam => {
|
||||
return runSafe(() => {
|
||||
let document = documents.get(documentLinkParam.textDocument.uri);
|
||||
let links: DocumentLink[] = [];
|
||||
if (document) {
|
||||
let documentContext = getDocumentContext(document.uri, workspaceFolders);
|
||||
languageModes.getAllModesInDocument(document).forEach(m => {
|
||||
if (m.findDocumentLinks) {
|
||||
pushAll(links, m.findDocumentLinks(document, documentContext));
|
||||
}
|
||||
});
|
||||
}
|
||||
return links;
|
||||
}, [], `Error while document links for ${documentLinkParam.textDocument.uri}`);
|
||||
});
|
||||
|
||||
|
||||
|
||||
connection.onDocumentSymbol(documentSymbolParms => {
|
||||
return runSafe(() => {
|
||||
let document = documents.get(documentSymbolParms.textDocument.uri);
|
||||
let symbols: SymbolInformation[] = [];
|
||||
languageModes.getAllModesInDocument(document).forEach(m => {
|
||||
if (m.findDocumentSymbols) {
|
||||
pushAll(symbols, m.findDocumentSymbols(document));
|
||||
}
|
||||
});
|
||||
return symbols;
|
||||
}, [], `Error while computing document symbols for ${documentSymbolParms.textDocument.uri}`);
|
||||
});
|
||||
|
||||
connection.onRequest(DocumentColorRequest.type, params => {
|
||||
return runSafe(() => {
|
||||
let infos: ColorInformation[] = [];
|
||||
let document = documents.get(params.textDocument.uri);
|
||||
if (document) {
|
||||
languageModes.getAllModesInDocument(document).forEach(m => {
|
||||
if (m.findDocumentColors) {
|
||||
pushAll(infos, m.findDocumentColors(document));
|
||||
}
|
||||
});
|
||||
}
|
||||
return infos;
|
||||
}, [], `Error while computing document colors for ${params.textDocument.uri}`);
|
||||
});
|
||||
|
||||
connection.onRequest(ColorPresentationRequest.type, params => {
|
||||
return runSafe(() => {
|
||||
let document = documents.get(params.textDocument.uri);
|
||||
if (document) {
|
||||
let mode = languageModes.getModeAtPosition(document, params.range.start);
|
||||
if (mode && mode.getColorPresentations) {
|
||||
return mode.getColorPresentations(document, params.color, params.range);
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}, [], `Error while computing color presentations for ${params.textDocument.uri}`);
|
||||
});
|
||||
|
||||
connection.onRequest(TagCloseRequest.type, params => {
|
||||
return runSafe(() => {
|
||||
let document = documents.get(params.textDocument.uri);
|
||||
if (document) {
|
||||
let pos = params.position;
|
||||
if (pos.character > 0) {
|
||||
let mode = languageModes.getModeAtPosition(document, Position.create(pos.line, pos.character - 1));
|
||||
if (mode && mode.doAutoClose) {
|
||||
return mode.doAutoClose(document, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}, null, `Error while computing tag close actions for ${params.textDocument.uri}`);
|
||||
});
|
||||
|
||||
|
||||
// Listen on the connection
|
||||
connection.listen();
|
83
my-snippets/laravel-blade/server/src/languageModelCache.ts
Normal file
83
my-snippets/laravel-blade/server/src/languageModelCache.ts
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { TextDocument } from 'vscode-languageserver';
|
||||
|
||||
export interface LanguageModelCache<T> {
|
||||
get(document: TextDocument): T;
|
||||
onDocumentRemoved(document: TextDocument): void;
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
export function getLanguageModelCache<T>(maxEntries: number, cleanupIntervalTimeInSec: number, parse: (document: TextDocument) => T): LanguageModelCache<T> {
|
||||
let languageModels: { [uri: string]: { version: number, languageId: string, cTime: number, languageModel: T } } = {};
|
||||
let nModels = 0;
|
||||
|
||||
let cleanupInterval: NodeJS.Timer | undefined = void 0;
|
||||
if (cleanupIntervalTimeInSec > 0) {
|
||||
cleanupInterval = setInterval(() => {
|
||||
let cutoffTime = Date.now() - cleanupIntervalTimeInSec * 1000;
|
||||
let uris = Object.keys(languageModels);
|
||||
for (let uri of uris) {
|
||||
let languageModelInfo = languageModels[uri];
|
||||
if (languageModelInfo.cTime < cutoffTime) {
|
||||
delete languageModels[uri];
|
||||
nModels--;
|
||||
}
|
||||
}
|
||||
}, cleanupIntervalTimeInSec * 1000);
|
||||
}
|
||||
|
||||
return {
|
||||
get(document: TextDocument): T {
|
||||
let version = document.version;
|
||||
let languageId = document.languageId;
|
||||
let languageModelInfo = languageModels[document.uri];
|
||||
if (languageModelInfo && languageModelInfo.version === version && languageModelInfo.languageId === languageId) {
|
||||
languageModelInfo.cTime = Date.now();
|
||||
return languageModelInfo.languageModel;
|
||||
}
|
||||
let languageModel = parse(document);
|
||||
languageModels[document.uri] = { languageModel, version, languageId, cTime: Date.now() };
|
||||
if (!languageModelInfo) {
|
||||
nModels++;
|
||||
}
|
||||
|
||||
if (nModels === maxEntries) {
|
||||
let oldestTime = Number.MAX_VALUE;
|
||||
let oldestUri = null;
|
||||
for (let uri in languageModels) {
|
||||
let languageModelInfo = languageModels[uri];
|
||||
if (languageModelInfo.cTime < oldestTime) {
|
||||
oldestUri = uri;
|
||||
oldestTime = languageModelInfo.cTime;
|
||||
}
|
||||
}
|
||||
if (oldestUri) {
|
||||
delete languageModels[oldestUri];
|
||||
nModels--;
|
||||
}
|
||||
}
|
||||
return languageModel;
|
||||
|
||||
},
|
||||
onDocumentRemoved(document: TextDocument) {
|
||||
let uri = document.uri;
|
||||
if (languageModels[uri]) {
|
||||
delete languageModels[uri];
|
||||
nModels--;
|
||||
}
|
||||
},
|
||||
dispose() {
|
||||
if (typeof cleanupInterval !== 'undefined') {
|
||||
clearInterval(cleanupInterval);
|
||||
cleanupInterval = void 0;
|
||||
languageModels = {};
|
||||
nModels = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
74
my-snippets/laravel-blade/server/src/modes/cssMode.ts
Normal file
74
my-snippets/laravel-blade/server/src/modes/cssMode.ts
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { LanguageModelCache, getLanguageModelCache } from '../languageModelCache';
|
||||
import { TextDocument, Position, Range } from 'vscode-languageserver-types';
|
||||
import { getCSSLanguageService, Stylesheet, ICompletionParticipant } from 'vscode-css-languageservice';
|
||||
import { LanguageMode, Settings } from './languageModes';
|
||||
import { HTMLDocumentRegions, CSS_STYLE_RULE } from './embeddedSupport';
|
||||
import { Color } from 'vscode-languageserver-protocol/lib/protocol.colorProvider.proposed';
|
||||
|
||||
export function getCSSMode(documentRegions: LanguageModelCache<HTMLDocumentRegions>): LanguageMode {
|
||||
let cssLanguageService = getCSSLanguageService();
|
||||
let embeddedCSSDocuments = getLanguageModelCache<TextDocument>(10, 60, document => documentRegions.get(document).getEmbeddedDocument('css'));
|
||||
let cssStylesheets = getLanguageModelCache<Stylesheet>(10, 60, document => cssLanguageService.parseStylesheet(document));
|
||||
|
||||
return {
|
||||
getId() {
|
||||
return 'css';
|
||||
},
|
||||
configure(options: any) {
|
||||
cssLanguageService.configure(options && options.css);
|
||||
},
|
||||
doValidation(document: TextDocument, settings?: Settings) {
|
||||
let embedded = embeddedCSSDocuments.get(document);
|
||||
return cssLanguageService.doValidation(embedded, cssStylesheets.get(embedded), settings && settings.css);
|
||||
},
|
||||
doComplete(document: TextDocument, position: Position) {
|
||||
let embedded = embeddedCSSDocuments.get(document);
|
||||
return cssLanguageService.doComplete(embedded, position, cssStylesheets.get(embedded));
|
||||
},
|
||||
setCompletionParticipants(registeredCompletionParticipants: ICompletionParticipant[]) {
|
||||
cssLanguageService.setCompletionParticipants(registeredCompletionParticipants);
|
||||
},
|
||||
doHover(document: TextDocument, position: Position) {
|
||||
let embedded = embeddedCSSDocuments.get(document);
|
||||
return cssLanguageService.doHover(embedded, position, cssStylesheets.get(embedded));
|
||||
},
|
||||
findDocumentHighlight(document: TextDocument, position: Position) {
|
||||
let embedded = embeddedCSSDocuments.get(document);
|
||||
return cssLanguageService.findDocumentHighlights(embedded, position, cssStylesheets.get(embedded));
|
||||
},
|
||||
findDocumentSymbols(document: TextDocument) {
|
||||
let embedded = embeddedCSSDocuments.get(document);
|
||||
return cssLanguageService.findDocumentSymbols(embedded, cssStylesheets.get(embedded)).filter(s => s.name !== CSS_STYLE_RULE);
|
||||
},
|
||||
findDefinition(document: TextDocument, position: Position) {
|
||||
let embedded = embeddedCSSDocuments.get(document);
|
||||
return cssLanguageService.findDefinition(embedded, position, cssStylesheets.get(embedded));
|
||||
},
|
||||
findReferences(document: TextDocument, position: Position) {
|
||||
let embedded = embeddedCSSDocuments.get(document);
|
||||
return cssLanguageService.findReferences(embedded, position, cssStylesheets.get(embedded));
|
||||
},
|
||||
findDocumentColors(document: TextDocument) {
|
||||
let embedded = embeddedCSSDocuments.get(document);
|
||||
return cssLanguageService.findDocumentColors(embedded, cssStylesheets.get(embedded));
|
||||
},
|
||||
getColorPresentations(document: TextDocument, color: Color, range: Range) {
|
||||
let embedded = embeddedCSSDocuments.get(document);
|
||||
return cssLanguageService.getColorPresentations(embedded, cssStylesheets.get(embedded), color, range);
|
||||
},
|
||||
onDocumentRemoved(document: TextDocument) {
|
||||
embeddedCSSDocuments.onDocumentRemoved(document);
|
||||
cssStylesheets.onDocumentRemoved(document);
|
||||
},
|
||||
dispose() {
|
||||
embeddedCSSDocuments.dispose();
|
||||
cssStylesheets.dispose();
|
||||
}
|
||||
};
|
||||
}
|
233
my-snippets/laravel-blade/server/src/modes/embeddedSupport.ts
Normal file
233
my-snippets/laravel-blade/server/src/modes/embeddedSupport.ts
Normal file
|
@ -0,0 +1,233 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
|
||||
import { TextDocument, Position, LanguageService, TokenType, Range } from 'vscode-html-languageservice';
|
||||
|
||||
export interface LanguageRange extends Range {
|
||||
languageId: string | undefined;
|
||||
attributeValue?: boolean;
|
||||
}
|
||||
|
||||
export interface HTMLDocumentRegions {
|
||||
getEmbeddedDocument(languageId: string, ignoreAttributeValues?: boolean): TextDocument;
|
||||
getLanguageRanges(range: Range): LanguageRange[];
|
||||
getLanguageAtPosition(position: Position): string | undefined;
|
||||
getLanguagesInDocument(): string[];
|
||||
getImportedScripts(): string[];
|
||||
}
|
||||
|
||||
export var CSS_STYLE_RULE = '__';
|
||||
|
||||
interface EmbeddedRegion { languageId: string | undefined; start: number; end: number; attributeValue?: boolean; }
|
||||
|
||||
|
||||
export function getDocumentRegions(languageService: LanguageService, document: TextDocument): HTMLDocumentRegions {
|
||||
let regions: EmbeddedRegion[] = [];
|
||||
let scanner = languageService.createScanner(document.getText());
|
||||
let lastTagName: string = '';
|
||||
let lastAttributeName: string | null = null;
|
||||
let languageIdFromType: string | undefined = undefined;
|
||||
let importedScripts: string[] = [];
|
||||
|
||||
let token = scanner.scan();
|
||||
while (token !== TokenType.EOS) {
|
||||
switch (token) {
|
||||
case TokenType.StartTag:
|
||||
lastTagName = scanner.getTokenText();
|
||||
lastAttributeName = null;
|
||||
languageIdFromType = 'javascript';
|
||||
break;
|
||||
case TokenType.Styles:
|
||||
regions.push({ languageId: 'css', start: scanner.getTokenOffset(), end: scanner.getTokenEnd() });
|
||||
break;
|
||||
case TokenType.Script:
|
||||
regions.push({ languageId: languageIdFromType, start: scanner.getTokenOffset(), end: scanner.getTokenEnd() });
|
||||
break;
|
||||
case TokenType.AttributeName:
|
||||
lastAttributeName = scanner.getTokenText();
|
||||
break;
|
||||
case TokenType.AttributeValue:
|
||||
if (lastAttributeName === 'src' && lastTagName.toLowerCase() === 'script') {
|
||||
let value = scanner.getTokenText();
|
||||
if (value[0] === '\'' || value[0] === '"') {
|
||||
value = value.substr(1, value.length - 1);
|
||||
}
|
||||
importedScripts.push(value);
|
||||
} else if (lastAttributeName === 'type' && lastTagName.toLowerCase() === 'script') {
|
||||
if (/["'](module|(text|application)\/(java|ecma)script)["']/.test(scanner.getTokenText())) {
|
||||
languageIdFromType = 'javascript';
|
||||
} else {
|
||||
languageIdFromType = void 0;
|
||||
}
|
||||
} else {
|
||||
let attributeLanguageId = getAttributeLanguage(lastAttributeName!);
|
||||
if (attributeLanguageId) {
|
||||
let start = scanner.getTokenOffset();
|
||||
let end = scanner.getTokenEnd();
|
||||
let firstChar = document.getText()[start];
|
||||
if (firstChar === '\'' || firstChar === '"') {
|
||||
start++;
|
||||
end--;
|
||||
}
|
||||
regions.push({ languageId: attributeLanguageId, start, end, attributeValue: true });
|
||||
}
|
||||
}
|
||||
lastAttributeName = null;
|
||||
break;
|
||||
}
|
||||
token = scanner.scan();
|
||||
}
|
||||
return {
|
||||
getLanguageRanges: (range: Range) => getLanguageRanges(document, regions, range),
|
||||
getEmbeddedDocument: (languageId: string, ignoreAttributeValues: boolean) => getEmbeddedDocument(document, regions, languageId, ignoreAttributeValues),
|
||||
getLanguageAtPosition: (position: Position) => getLanguageAtPosition(document, regions, position),
|
||||
getLanguagesInDocument: () => getLanguagesInDocument(document, regions),
|
||||
getImportedScripts: () => importedScripts
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function getLanguageRanges(document: TextDocument, regions: EmbeddedRegion[], range: Range): LanguageRange[] {
|
||||
let result: LanguageRange[] = [];
|
||||
let currentPos = range ? range.start : Position.create(0, 0);
|
||||
let currentOffset = range ? document.offsetAt(range.start) : 0;
|
||||
let endOffset = range ? document.offsetAt(range.end) : document.getText().length;
|
||||
for (let region of regions) {
|
||||
if (region.end > currentOffset && region.start < endOffset) {
|
||||
let start = Math.max(region.start, currentOffset);
|
||||
let startPos = document.positionAt(start);
|
||||
if (currentOffset < region.start) {
|
||||
result.push({
|
||||
start: currentPos,
|
||||
end: startPos,
|
||||
languageId: 'html'
|
||||
});
|
||||
}
|
||||
let end = Math.min(region.end, endOffset);
|
||||
let endPos = document.positionAt(end);
|
||||
if (end > region.start) {
|
||||
result.push({
|
||||
start: startPos,
|
||||
end: endPos,
|
||||
languageId: region.languageId,
|
||||
attributeValue: region.attributeValue
|
||||
});
|
||||
}
|
||||
currentOffset = end;
|
||||
currentPos = endPos;
|
||||
}
|
||||
}
|
||||
if (currentOffset < endOffset) {
|
||||
let endPos = range ? range.end : document.positionAt(endOffset);
|
||||
result.push({
|
||||
start: currentPos,
|
||||
end: endPos,
|
||||
languageId: 'html'
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function getLanguagesInDocument(document: TextDocument, regions: EmbeddedRegion[]): string[] {
|
||||
let result = [];
|
||||
for (let region of regions) {
|
||||
if (region.languageId && result.indexOf(region.languageId) === -1) {
|
||||
result.push(region.languageId);
|
||||
if (result.length === 3) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
result.push('html');
|
||||
return result;
|
||||
}
|
||||
|
||||
function getLanguageAtPosition(document: TextDocument, regions: EmbeddedRegion[], position: Position): string | undefined {
|
||||
let offset = document.offsetAt(position);
|
||||
for (let region of regions) {
|
||||
if (region.start <= offset) {
|
||||
if (offset <= region.end) {
|
||||
return region.languageId;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 'html';
|
||||
}
|
||||
|
||||
function getEmbeddedDocument(document: TextDocument, contents: EmbeddedRegion[], languageId: string, ignoreAttributeValues: boolean): TextDocument {
|
||||
let currentPos = 0;
|
||||
let oldContent = document.getText();
|
||||
let result = '';
|
||||
let lastSuffix = '';
|
||||
for (let c of contents) {
|
||||
if (c.languageId === languageId && (!ignoreAttributeValues || !c.attributeValue)) {
|
||||
result = substituteWithWhitespace(result, currentPos, c.start, oldContent, lastSuffix, getPrefix(c));
|
||||
result += oldContent.substring(c.start, c.end);
|
||||
currentPos = c.end;
|
||||
lastSuffix = getSuffix(c);
|
||||
}
|
||||
}
|
||||
result = substituteWithWhitespace(result, currentPos, oldContent.length, oldContent, lastSuffix, '');
|
||||
return TextDocument.create(document.uri, languageId, document.version, result);
|
||||
}
|
||||
|
||||
function getPrefix(c: EmbeddedRegion) {
|
||||
if (c.attributeValue) {
|
||||
switch (c.languageId) {
|
||||
case 'css': return CSS_STYLE_RULE + '{';
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
function getSuffix(c: EmbeddedRegion) {
|
||||
if (c.attributeValue) {
|
||||
switch (c.languageId) {
|
||||
case 'css': return '}';
|
||||
case 'javascript': return ';';
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function substituteWithWhitespace(result: string, start: number, end: number, oldContent: string, before: string, after: string) {
|
||||
let accumulatedWS = 0;
|
||||
result += before;
|
||||
for (let i = start + before.length; i < end; i++) {
|
||||
let ch = oldContent[i];
|
||||
if (ch === '\n' || ch === '\r') {
|
||||
// only write new lines, skip the whitespace
|
||||
accumulatedWS = 0;
|
||||
result += ch;
|
||||
} else {
|
||||
accumulatedWS++;
|
||||
}
|
||||
}
|
||||
result = append(result, ' ', accumulatedWS - after.length);
|
||||
result += after;
|
||||
return result;
|
||||
}
|
||||
|
||||
function append(result: string, str: string, n: number): string {
|
||||
while (n > 0) {
|
||||
if (n & 1) {
|
||||
result += str;
|
||||
}
|
||||
n >>= 1;
|
||||
str += str;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function getAttributeLanguage(attributeName: string): string | null {
|
||||
let match = attributeName.match(/^(style)$|^(on\w+)$/i);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
return match[1] ? 'css' : 'javascript';
|
||||
}
|
95
my-snippets/laravel-blade/server/src/modes/formatting.ts
Normal file
95
my-snippets/laravel-blade/server/src/modes/formatting.ts
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { applyEdits } from '../utils/edits';
|
||||
import { TextDocument, Range, TextEdit, FormattingOptions, Position } from 'vscode-languageserver-types';
|
||||
import { LanguageModes, Settings, LanguageModeRange } from './languageModes';
|
||||
import { pushAll } from '../utils/arrays';
|
||||
import { isEOL } from '../utils/strings';
|
||||
|
||||
export function format(languageModes: LanguageModes, document: TextDocument, formatRange: Range, formattingOptions: FormattingOptions, settings: Settings | undefined, enabledModes: { [mode: string]: boolean }) {
|
||||
let result: TextEdit[] = [];
|
||||
|
||||
let endPos = formatRange.end;
|
||||
let endOffset = document.offsetAt(endPos);
|
||||
let content = document.getText();
|
||||
if (endPos.character === 0 && endPos.line > 0 && endOffset !== content.length) {
|
||||
// if selection ends after a new line, exclude that new line
|
||||
let prevLineStart = document.offsetAt(Position.create(endPos.line - 1, 0));
|
||||
while (isEOL(content, endOffset - 1) && endOffset > prevLineStart) {
|
||||
endOffset--;
|
||||
}
|
||||
formatRange = Range.create(formatRange.start, document.positionAt(endOffset));
|
||||
}
|
||||
|
||||
|
||||
// run the html formatter on the full range and pass the result content to the embedded formatters.
|
||||
// from the final content create a single edit
|
||||
// advantages of this approach are
|
||||
// - correct indents in the html document
|
||||
// - correct initial indent for embedded formatters
|
||||
// - no worrying of overlapping edits
|
||||
|
||||
// make sure we start in html
|
||||
let allRanges = languageModes.getModesInRange(document, formatRange);
|
||||
let i = 0;
|
||||
let startPos = formatRange.start;
|
||||
let isHTML = (range: LanguageModeRange) => range.mode && range.mode.getId() === 'html';
|
||||
|
||||
while (i < allRanges.length && !isHTML(allRanges[i])) {
|
||||
let range = allRanges[i];
|
||||
if (!range.attributeValue && range.mode && range.mode.format) {
|
||||
let edits = range.mode.format(document, Range.create(startPos, range.end), formattingOptions, settings);
|
||||
pushAll(result, edits);
|
||||
}
|
||||
startPos = range.end;
|
||||
i++;
|
||||
}
|
||||
if (i === allRanges.length) {
|
||||
return result;
|
||||
}
|
||||
// modify the range
|
||||
formatRange = Range.create(startPos, formatRange.end);
|
||||
|
||||
// perform a html format and apply changes to a new document
|
||||
let htmlMode = languageModes.getMode('html')!;
|
||||
let htmlEdits = htmlMode.format!(document, formatRange, formattingOptions, settings);
|
||||
let htmlFormattedContent = applyEdits(document, htmlEdits);
|
||||
let newDocument = TextDocument.create(document.uri + '.tmp', document.languageId, document.version, htmlFormattedContent);
|
||||
try {
|
||||
// run embedded formatters on html formatted content: - formatters see correct initial indent
|
||||
let afterFormatRangeLength = document.getText().length - document.offsetAt(formatRange.end); // length of unchanged content after replace range
|
||||
let newFormatRange = Range.create(formatRange.start, newDocument.positionAt(htmlFormattedContent.length - afterFormatRangeLength));
|
||||
let embeddedRanges = languageModes.getModesInRange(newDocument, newFormatRange);
|
||||
|
||||
let embeddedEdits: TextEdit[] = [];
|
||||
|
||||
for (let r of embeddedRanges) {
|
||||
let mode = r.mode;
|
||||
if (mode && mode.format && enabledModes[mode.getId()] && !r.attributeValue) {
|
||||
let edits = mode.format(newDocument, r, formattingOptions, settings);
|
||||
for (let edit of edits) {
|
||||
embeddedEdits.push(edit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (embeddedEdits.length === 0) {
|
||||
pushAll(result, htmlEdits);
|
||||
return result;
|
||||
}
|
||||
|
||||
// apply all embedded format edits and create a single edit for all changes
|
||||
let resultContent = applyEdits(newDocument, embeddedEdits);
|
||||
let resultReplaceText = resultContent.substring(document.offsetAt(formatRange.start), resultContent.length - afterFormatRangeLength);
|
||||
|
||||
result.push(TextEdit.replace(formatRange, resultReplaceText));
|
||||
return result;
|
||||
} finally {
|
||||
languageModes.onDocumentRemoved(newDocument);
|
||||
}
|
||||
|
||||
}
|
98
my-snippets/laravel-blade/server/src/modes/htmlMode.ts
Normal file
98
my-snippets/laravel-blade/server/src/modes/htmlMode.ts
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { getLanguageModelCache } from '../languageModelCache';
|
||||
import { LanguageService as HTMLLanguageService, HTMLDocument, DocumentContext, FormattingOptions, HTMLFormatConfiguration, TokenType } from 'vscode-html-languageservice';
|
||||
import { TextDocument, Position, Range } from 'vscode-languageserver-types';
|
||||
import { LanguageMode, Settings } from './languageModes';
|
||||
|
||||
export function getHTMLMode(htmlLanguageService: HTMLLanguageService): LanguageMode {
|
||||
let globalSettings: Settings = {};
|
||||
let htmlDocuments = getLanguageModelCache<HTMLDocument>(10, 60, document => htmlLanguageService.parseHTMLDocument(document));
|
||||
let completionParticipants = [];
|
||||
return {
|
||||
getId() {
|
||||
return 'html';
|
||||
},
|
||||
configure(options: any) {
|
||||
globalSettings = options;
|
||||
},
|
||||
doComplete(document: TextDocument, position: Position, settings: Settings = globalSettings) {
|
||||
let options = settings && settings.html && settings.html.suggest;
|
||||
let doAutoComplete = settings && settings.html && settings.html.autoClosingTags;
|
||||
if (doAutoComplete) {
|
||||
options.hideAutoCompleteProposals = true;
|
||||
}
|
||||
|
||||
const htmlDocument = htmlDocuments.get(document);
|
||||
const offset = document.offsetAt(position);
|
||||
const node = htmlDocument.findNodeBefore(offset);
|
||||
const scanner = htmlLanguageService.createScanner(document.getText(), node.start);
|
||||
let token = scanner.scan();
|
||||
while (token !== TokenType.EOS && scanner.getTokenOffset() <= offset) {
|
||||
if (token === TokenType.Content && offset <= scanner.getTokenEnd()) {
|
||||
completionParticipants.forEach(participant => { if (participant.onHtmlContent) { participant.onHtmlContent(); } });
|
||||
break;
|
||||
}
|
||||
token = scanner.scan();
|
||||
}
|
||||
return htmlLanguageService.doComplete(document, position, htmlDocument, options);
|
||||
},
|
||||
setCompletionParticipants(registeredCompletionParticipants: any[]) {
|
||||
completionParticipants = registeredCompletionParticipants;
|
||||
},
|
||||
doHover(document: TextDocument, position: Position) {
|
||||
return htmlLanguageService.doHover(document, position, htmlDocuments.get(document));
|
||||
},
|
||||
findDocumentHighlight(document: TextDocument, position: Position) {
|
||||
return htmlLanguageService.findDocumentHighlights(document, position, htmlDocuments.get(document));
|
||||
},
|
||||
findDocumentLinks(document: TextDocument, documentContext: DocumentContext) {
|
||||
return htmlLanguageService.findDocumentLinks(document, documentContext);
|
||||
},
|
||||
findDocumentSymbols(document: TextDocument) {
|
||||
return htmlLanguageService.findDocumentSymbols(document, htmlDocuments.get(document));
|
||||
},
|
||||
format(document: TextDocument, range: Range, formatParams: FormattingOptions, settings: Settings = globalSettings) {
|
||||
let formatSettings: HTMLFormatConfiguration = settings && settings.html && settings.html.format;
|
||||
if (formatSettings) {
|
||||
formatSettings = merge(formatSettings, {});
|
||||
} else {
|
||||
formatSettings = {};
|
||||
}
|
||||
if (formatSettings.contentUnformatted) {
|
||||
formatSettings.contentUnformatted = formatSettings.contentUnformatted + ',script';
|
||||
} else {
|
||||
formatSettings.contentUnformatted = 'script';
|
||||
}
|
||||
formatSettings = merge(formatParams, formatSettings);
|
||||
return htmlLanguageService.format(document, range, formatSettings);
|
||||
},
|
||||
doAutoClose(document: TextDocument, position: Position) {
|
||||
let offset = document.offsetAt(position);
|
||||
let text = document.getText();
|
||||
if (offset > 0 && text.charAt(offset - 1).match(/[>\/]/g)) {
|
||||
return htmlLanguageService.doTagComplete(document, position, htmlDocuments.get(document));
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onDocumentRemoved(document: TextDocument) {
|
||||
htmlDocuments.onDocumentRemoved(document);
|
||||
},
|
||||
dispose() {
|
||||
htmlDocuments.dispose();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function merge(src: any, dst: any): any {
|
||||
for (var key in src) {
|
||||
if (src.hasOwnProperty(key)) {
|
||||
dst[key] = src[key];
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
411
my-snippets/laravel-blade/server/src/modes/javascriptMode.ts
Normal file
411
my-snippets/laravel-blade/server/src/modes/javascriptMode.ts
Normal file
|
@ -0,0 +1,411 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { LanguageModelCache, getLanguageModelCache } from '../languageModelCache';
|
||||
import { SymbolInformation, SymbolKind, CompletionItem, Location, SignatureHelp, SignatureInformation, ParameterInformation, Definition, TextEdit, TextDocument, Diagnostic, DiagnosticSeverity, Range, CompletionItemKind, Hover, MarkedString, DocumentHighlight, DocumentHighlightKind, CompletionList, Position, FormattingOptions } from 'vscode-languageserver-types';
|
||||
import { LanguageMode, Settings } from './languageModes';
|
||||
import { getWordAtText, startsWith, isWhitespaceOnly, repeat } from '../utils/strings';
|
||||
import { HTMLDocumentRegions } from './embeddedSupport';
|
||||
|
||||
import * as ts from 'typescript';
|
||||
import { join } from 'path';
|
||||
|
||||
const FILE_NAME = 'vscode://javascript/1'; // the same 'file' is used for all contents
|
||||
const JQUERY_D_TS = join(__dirname, '../../lib/jquery.d.ts');
|
||||
|
||||
const JS_WORD_REGEX = /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g;
|
||||
|
||||
export function getJavascriptMode(documentRegions: LanguageModelCache<HTMLDocumentRegions>): LanguageMode {
|
||||
let jsDocuments = getLanguageModelCache<TextDocument>(10, 60, document => documentRegions.get(document).getEmbeddedDocument('javascript'));
|
||||
|
||||
let compilerOptions: ts.CompilerOptions = { allowNonTsExtensions: true, allowJs: true, lib: ['lib.es6.d.ts'], target: ts.ScriptTarget.Latest, moduleResolution: ts.ModuleResolutionKind.Classic };
|
||||
let currentTextDocument: TextDocument;
|
||||
let scriptFileVersion: number = 0;
|
||||
function updateCurrentTextDocument(doc: TextDocument) {
|
||||
if (!currentTextDocument || doc.uri !== currentTextDocument.uri || doc.version !== currentTextDocument.version) {
|
||||
currentTextDocument = jsDocuments.get(doc);
|
||||
scriptFileVersion++;
|
||||
}
|
||||
}
|
||||
const host: ts.LanguageServiceHost = {
|
||||
getCompilationSettings: () => compilerOptions,
|
||||
getScriptFileNames: () => [FILE_NAME, JQUERY_D_TS],
|
||||
getScriptKind: () => ts.ScriptKind.JS,
|
||||
getScriptVersion: (fileName: string) => {
|
||||
if (fileName === FILE_NAME) {
|
||||
return String(scriptFileVersion);
|
||||
}
|
||||
return '1'; // default lib an jquery.d.ts are static
|
||||
},
|
||||
getScriptSnapshot: (fileName: string) => {
|
||||
let text = '';
|
||||
if (startsWith(fileName, 'vscode:')) {
|
||||
if (fileName === FILE_NAME) {
|
||||
text = currentTextDocument.getText();
|
||||
}
|
||||
} else {
|
||||
text = ts.sys.readFile(fileName) || '';
|
||||
}
|
||||
return {
|
||||
getText: (start, end) => text.substring(start, end),
|
||||
getLength: () => text.length,
|
||||
getChangeRange: () => void 0
|
||||
};
|
||||
},
|
||||
getCurrentDirectory: () => '',
|
||||
getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options)
|
||||
};
|
||||
let jsLanguageService = ts.createLanguageService(host);
|
||||
|
||||
let globalSettings: Settings = {};
|
||||
|
||||
return {
|
||||
getId() {
|
||||
return 'javascript';
|
||||
},
|
||||
configure(options: any) {
|
||||
globalSettings = options;
|
||||
},
|
||||
doValidation(document: TextDocument): Diagnostic[] {
|
||||
updateCurrentTextDocument(document);
|
||||
const syntaxDiagnostics = jsLanguageService.getSyntacticDiagnostics(FILE_NAME);
|
||||
const semanticDiagnostics = jsLanguageService.getSemanticDiagnostics(FILE_NAME);
|
||||
return syntaxDiagnostics.concat(semanticDiagnostics).map((diag: ts.Diagnostic): Diagnostic => {
|
||||
return {
|
||||
range: convertRange(currentTextDocument, diag),
|
||||
severity: DiagnosticSeverity.Error,
|
||||
source: 'js',
|
||||
message: ts.flattenDiagnosticMessageText(diag.messageText, '\n')
|
||||
};
|
||||
});
|
||||
},
|
||||
doComplete(document: TextDocument, position: Position): CompletionList {
|
||||
updateCurrentTextDocument(document);
|
||||
let offset = currentTextDocument.offsetAt(position);
|
||||
let completions = jsLanguageService.getCompletionsAtPosition(FILE_NAME, offset, { includeExternalModuleExports: false, includeInsertTextCompletions: false });
|
||||
if (!completions) {
|
||||
return { isIncomplete: false, items: [] };
|
||||
}
|
||||
let replaceRange = convertRange(currentTextDocument, getWordAtText(currentTextDocument.getText(), offset, JS_WORD_REGEX));
|
||||
return {
|
||||
isIncomplete: false,
|
||||
items: completions.entries.map(entry => {
|
||||
return {
|
||||
uri: document.uri,
|
||||
position: position,
|
||||
label: entry.name,
|
||||
sortText: entry.sortText,
|
||||
kind: convertKind(entry.kind),
|
||||
textEdit: TextEdit.replace(replaceRange, entry.name),
|
||||
data: { // data used for resolving item details (see 'doResolve')
|
||||
languageId: 'javascript',
|
||||
uri: document.uri,
|
||||
offset: offset
|
||||
}
|
||||
};
|
||||
})
|
||||
};
|
||||
},
|
||||
doResolve(document: TextDocument, item: CompletionItem): CompletionItem {
|
||||
updateCurrentTextDocument(document);
|
||||
let details = jsLanguageService.getCompletionEntryDetails(FILE_NAME, item.data.offset, item.label, undefined, undefined);
|
||||
if (details) {
|
||||
item.detail = ts.displayPartsToString(details.displayParts);
|
||||
item.documentation = ts.displayPartsToString(details.documentation);
|
||||
delete item.data;
|
||||
}
|
||||
return item;
|
||||
},
|
||||
doHover(document: TextDocument, position: Position): Hover | null {
|
||||
updateCurrentTextDocument(document);
|
||||
let info = jsLanguageService.getQuickInfoAtPosition(FILE_NAME, currentTextDocument.offsetAt(position));
|
||||
if (info) {
|
||||
let contents = ts.displayPartsToString(info.displayParts);
|
||||
return {
|
||||
range: convertRange(currentTextDocument, info.textSpan),
|
||||
contents: MarkedString.fromPlainText(contents)
|
||||
};
|
||||
}
|
||||
return null;
|
||||
},
|
||||
doSignatureHelp(document: TextDocument, position: Position): SignatureHelp | null {
|
||||
updateCurrentTextDocument(document);
|
||||
let signHelp = jsLanguageService.getSignatureHelpItems(FILE_NAME, currentTextDocument.offsetAt(position));
|
||||
if (signHelp) {
|
||||
let ret: SignatureHelp = {
|
||||
activeSignature: signHelp.selectedItemIndex,
|
||||
activeParameter: signHelp.argumentIndex,
|
||||
signatures: []
|
||||
};
|
||||
signHelp.items.forEach(item => {
|
||||
|
||||
let signature: SignatureInformation = {
|
||||
label: '',
|
||||
documentation: undefined,
|
||||
parameters: []
|
||||
};
|
||||
|
||||
signature.label += ts.displayPartsToString(item.prefixDisplayParts);
|
||||
item.parameters.forEach((p, i, a) => {
|
||||
let label = ts.displayPartsToString(p.displayParts);
|
||||
let parameter: ParameterInformation = {
|
||||
label: label,
|
||||
documentation: ts.displayPartsToString(p.documentation)
|
||||
};
|
||||
signature.label += label;
|
||||
signature.parameters!.push(parameter);
|
||||
if (i < a.length - 1) {
|
||||
signature.label += ts.displayPartsToString(item.separatorDisplayParts);
|
||||
}
|
||||
});
|
||||
signature.label += ts.displayPartsToString(item.suffixDisplayParts);
|
||||
ret.signatures.push(signature);
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
findDocumentHighlight(document: TextDocument, position: Position): DocumentHighlight[] {
|
||||
updateCurrentTextDocument(document);
|
||||
let occurrences = jsLanguageService.getOccurrencesAtPosition(FILE_NAME, currentTextDocument.offsetAt(position));
|
||||
if (occurrences) {
|
||||
return occurrences.map(entry => {
|
||||
return {
|
||||
range: convertRange(currentTextDocument, entry.textSpan),
|
||||
kind: <DocumentHighlightKind>(entry.isWriteAccess ? DocumentHighlightKind.Write : DocumentHighlightKind.Text)
|
||||
};
|
||||
});
|
||||
}
|
||||
return [];
|
||||
},
|
||||
findDocumentSymbols(document: TextDocument): SymbolInformation[] {
|
||||
updateCurrentTextDocument(document);
|
||||
let items = jsLanguageService.getNavigationBarItems(FILE_NAME);
|
||||
if (items) {
|
||||
let result: SymbolInformation[] = [];
|
||||
let existing = Object.create(null);
|
||||
let collectSymbols = (item: ts.NavigationBarItem, containerLabel?: string) => {
|
||||
let sig = item.text + item.kind + item.spans[0].start;
|
||||
if (item.kind !== 'script' && !existing[sig]) {
|
||||
let symbol: SymbolInformation = {
|
||||
name: item.text,
|
||||
kind: convertSymbolKind(item.kind),
|
||||
location: {
|
||||
uri: document.uri,
|
||||
range: convertRange(currentTextDocument, item.spans[0])
|
||||
},
|
||||
containerName: containerLabel
|
||||
};
|
||||
existing[sig] = true;
|
||||
result.push(symbol);
|
||||
containerLabel = item.text;
|
||||
}
|
||||
|
||||
if (item.childItems && item.childItems.length > 0) {
|
||||
for (let child of item.childItems) {
|
||||
collectSymbols(child, containerLabel);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
items.forEach(item => collectSymbols(item));
|
||||
return result;
|
||||
}
|
||||
return [];
|
||||
},
|
||||
findDefinition(document: TextDocument, position: Position): Definition | null {
|
||||
updateCurrentTextDocument(document);
|
||||
let definition = jsLanguageService.getDefinitionAtPosition(FILE_NAME, currentTextDocument.offsetAt(position));
|
||||
if (definition) {
|
||||
return definition.filter(d => d.fileName === FILE_NAME).map(d => {
|
||||
return {
|
||||
uri: document.uri,
|
||||
range: convertRange(currentTextDocument, d.textSpan)
|
||||
};
|
||||
});
|
||||
}
|
||||
return null;
|
||||
},
|
||||
findReferences(document: TextDocument, position: Position): Location[] {
|
||||
updateCurrentTextDocument(document);
|
||||
let references = jsLanguageService.getReferencesAtPosition(FILE_NAME, currentTextDocument.offsetAt(position));
|
||||
if (references) {
|
||||
return references.filter(d => d.fileName === FILE_NAME).map(d => {
|
||||
return {
|
||||
uri: document.uri,
|
||||
range: convertRange(currentTextDocument, d.textSpan)
|
||||
};
|
||||
});
|
||||
}
|
||||
return [];
|
||||
},
|
||||
format(document: TextDocument, range: Range, formatParams: FormattingOptions, settings: Settings = globalSettings): TextEdit[] {
|
||||
currentTextDocument = documentRegions.get(document).getEmbeddedDocument('javascript', true);
|
||||
scriptFileVersion++;
|
||||
|
||||
let formatterSettings = settings && settings.javascript && settings.javascript.format;
|
||||
|
||||
let initialIndentLevel = computeInitialIndent(document, range, formatParams);
|
||||
let formatSettings = convertOptions(formatParams, formatterSettings, initialIndentLevel + 1);
|
||||
let start = currentTextDocument.offsetAt(range.start);
|
||||
let end = currentTextDocument.offsetAt(range.end);
|
||||
let lastLineRange = null;
|
||||
if (range.end.line > range.start.line && (range.end.character === 0 || isWhitespaceOnly(currentTextDocument.getText().substr(end - range.end.character, range.end.character)))) {
|
||||
end -= range.end.character;
|
||||
lastLineRange = Range.create(Position.create(range.end.line, 0), range.end);
|
||||
}
|
||||
let edits = jsLanguageService.getFormattingEditsForRange(FILE_NAME, start, end, formatSettings);
|
||||
if (edits) {
|
||||
let result = [];
|
||||
for (let edit of edits) {
|
||||
if (edit.span.start >= start && edit.span.start + edit.span.length <= end) {
|
||||
result.push({
|
||||
range: convertRange(currentTextDocument, edit.span),
|
||||
newText: edit.newText
|
||||
});
|
||||
}
|
||||
}
|
||||
if (lastLineRange) {
|
||||
result.push({
|
||||
range: lastLineRange,
|
||||
newText: generateIndent(initialIndentLevel, formatParams)
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return [];
|
||||
},
|
||||
onDocumentRemoved(document: TextDocument) {
|
||||
jsDocuments.onDocumentRemoved(document);
|
||||
},
|
||||
dispose() {
|
||||
jsLanguageService.dispose();
|
||||
jsDocuments.dispose();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function convertRange(document: TextDocument, span: { start: number | undefined, length: number | undefined }): Range {
|
||||
if (typeof span.start === 'undefined') {
|
||||
const pos = document.positionAt(0);
|
||||
return Range.create(pos, pos);
|
||||
}
|
||||
const startPosition = document.positionAt(span.start);
|
||||
const endPosition = document.positionAt(span.start + (span.length || 0));
|
||||
return Range.create(startPosition, endPosition);
|
||||
}
|
||||
|
||||
function convertKind(kind: string): CompletionItemKind {
|
||||
switch (kind) {
|
||||
case 'primitive type':
|
||||
case 'keyword':
|
||||
return CompletionItemKind.Keyword;
|
||||
case 'var':
|
||||
case 'local var':
|
||||
return CompletionItemKind.Variable;
|
||||
case 'property':
|
||||
case 'getter':
|
||||
case 'setter':
|
||||
return CompletionItemKind.Field;
|
||||
case 'function':
|
||||
case 'method':
|
||||
case 'construct':
|
||||
case 'call':
|
||||
case 'index':
|
||||
return CompletionItemKind.Function;
|
||||
case 'enum':
|
||||
return CompletionItemKind.Enum;
|
||||
case 'module':
|
||||
return CompletionItemKind.Module;
|
||||
case 'class':
|
||||
return CompletionItemKind.Class;
|
||||
case 'interface':
|
||||
return CompletionItemKind.Interface;
|
||||
case 'warning':
|
||||
return CompletionItemKind.File;
|
||||
}
|
||||
|
||||
return CompletionItemKind.Property;
|
||||
}
|
||||
|
||||
function convertSymbolKind(kind: string): SymbolKind {
|
||||
switch (kind) {
|
||||
case 'var':
|
||||
case 'local var':
|
||||
case 'const':
|
||||
return SymbolKind.Variable;
|
||||
case 'function':
|
||||
case 'local function':
|
||||
return SymbolKind.Function;
|
||||
case 'enum':
|
||||
return SymbolKind.Enum;
|
||||
case 'module':
|
||||
return SymbolKind.Module;
|
||||
case 'class':
|
||||
return SymbolKind.Class;
|
||||
case 'interface':
|
||||
return SymbolKind.Interface;
|
||||
case 'method':
|
||||
return SymbolKind.Method;
|
||||
case 'property':
|
||||
case 'getter':
|
||||
case 'setter':
|
||||
return SymbolKind.Property;
|
||||
}
|
||||
return SymbolKind.Variable;
|
||||
}
|
||||
|
||||
function convertOptions(options: FormattingOptions, formatSettings: any, initialIndentLevel: number): ts.FormatCodeOptions {
|
||||
return {
|
||||
ConvertTabsToSpaces: options.insertSpaces,
|
||||
TabSize: options.tabSize,
|
||||
IndentSize: options.tabSize,
|
||||
IndentStyle: ts.IndentStyle.Smart,
|
||||
NewLineCharacter: '\n',
|
||||
BaseIndentSize: options.tabSize * initialIndentLevel,
|
||||
InsertSpaceAfterCommaDelimiter: Boolean(!formatSettings || formatSettings.insertSpaceAfterCommaDelimiter),
|
||||
InsertSpaceAfterSemicolonInForStatements: Boolean(!formatSettings || formatSettings.insertSpaceAfterSemicolonInForStatements),
|
||||
InsertSpaceBeforeAndAfterBinaryOperators: Boolean(!formatSettings || formatSettings.insertSpaceBeforeAndAfterBinaryOperators),
|
||||
InsertSpaceAfterKeywordsInControlFlowStatements: Boolean(!formatSettings || formatSettings.insertSpaceAfterKeywordsInControlFlowStatements),
|
||||
InsertSpaceAfterFunctionKeywordForAnonymousFunctions: Boolean(!formatSettings || formatSettings.insertSpaceAfterFunctionKeywordForAnonymousFunctions),
|
||||
InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: Boolean(formatSettings && formatSettings.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis),
|
||||
InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: Boolean(formatSettings && formatSettings.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets),
|
||||
InsertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: Boolean(formatSettings && formatSettings.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces),
|
||||
InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: Boolean(formatSettings && formatSettings.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces),
|
||||
PlaceOpenBraceOnNewLineForControlBlocks: Boolean(formatSettings && formatSettings.placeOpenBraceOnNewLineForFunctions),
|
||||
PlaceOpenBraceOnNewLineForFunctions: Boolean(formatSettings && formatSettings.placeOpenBraceOnNewLineForControlBlocks)
|
||||
};
|
||||
}
|
||||
|
||||
function computeInitialIndent(document: TextDocument, range: Range, options: FormattingOptions) {
|
||||
let lineStart = document.offsetAt(Position.create(range.start.line, 0));
|
||||
let content = document.getText();
|
||||
|
||||
let i = lineStart;
|
||||
let nChars = 0;
|
||||
let tabSize = options.tabSize || 4;
|
||||
while (i < content.length) {
|
||||
let ch = content.charAt(i);
|
||||
if (ch === ' ') {
|
||||
nChars++;
|
||||
} else if (ch === '\t') {
|
||||
nChars += tabSize;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return Math.floor(nChars / tabSize);
|
||||
}
|
||||
|
||||
function generateIndent(level: number, options: FormattingOptions) {
|
||||
if (options.insertSpaces) {
|
||||
return repeat(' ', level * options.tabSize);
|
||||
} else {
|
||||
return repeat('\t', level);
|
||||
}
|
||||
}
|
143
my-snippets/laravel-blade/server/src/modes/languageModes.ts
Normal file
143
my-snippets/laravel-blade/server/src/modes/languageModes.ts
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { getLanguageService as getHTMLLanguageService, DocumentContext } from 'vscode-html-languageservice';
|
||||
import {
|
||||
CompletionItem, Location, SignatureHelp, Definition, TextEdit, TextDocument, Diagnostic, DocumentLink, Range,
|
||||
Hover, DocumentHighlight, CompletionList, Position, FormattingOptions, SymbolInformation
|
||||
} from 'vscode-languageserver-types';
|
||||
|
||||
import { ColorInformation, ColorPresentation, Color } from 'vscode-languageserver-protocol/lib/protocol.colorProvider.proposed';
|
||||
|
||||
import { getLanguageModelCache, LanguageModelCache } from '../languageModelCache';
|
||||
import { getDocumentRegions, HTMLDocumentRegions } from './embeddedSupport';
|
||||
import { getCSSMode } from './cssMode';
|
||||
import { getJavascriptMode } from './javascriptMode';
|
||||
import { getHTMLMode } from './htmlMode';
|
||||
|
||||
export { ColorInformation, ColorPresentation, Color };
|
||||
|
||||
export interface Settings {
|
||||
css?: any;
|
||||
html?: any;
|
||||
javascript?: any;
|
||||
emmet?: { [key: string]: any };
|
||||
}
|
||||
|
||||
export interface SettingProvider {
|
||||
getDocumentSettings(textDocument: TextDocument): Thenable<Settings>;
|
||||
}
|
||||
|
||||
export interface LanguageMode {
|
||||
getId(): string;
|
||||
configure?: (options: Settings) => void;
|
||||
doValidation?: (document: TextDocument, settings?: Settings) => Diagnostic[];
|
||||
doComplete?: (document: TextDocument, position: Position, settings?: Settings) => CompletionList | null;
|
||||
setCompletionParticipants?: (registeredCompletionParticipants: any[]) => void;
|
||||
doResolve?: (document: TextDocument, item: CompletionItem) => CompletionItem | null;
|
||||
doHover?: (document: TextDocument, position: Position) => Hover | null;
|
||||
doSignatureHelp?: (document: TextDocument, position: Position) => SignatureHelp | null;
|
||||
findDocumentHighlight?: (document: TextDocument, position: Position) => DocumentHighlight[];
|
||||
findDocumentSymbols?: (document: TextDocument) => SymbolInformation[];
|
||||
findDocumentLinks?: (document: TextDocument, documentContext: DocumentContext) => DocumentLink[];
|
||||
findDefinition?: (document: TextDocument, position: Position) => Definition | null;
|
||||
findReferences?: (document: TextDocument, position: Position) => Location[];
|
||||
format?: (document: TextDocument, range: Range, options: FormattingOptions, settings?: Settings) => TextEdit[];
|
||||
findDocumentColors?: (document: TextDocument) => ColorInformation[];
|
||||
getColorPresentations?: (document: TextDocument, color: Color, range: Range) => ColorPresentation[];
|
||||
doAutoClose?: (document: TextDocument, position: Position) => string | null;
|
||||
onDocumentRemoved(document: TextDocument): void;
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
export interface LanguageModes {
|
||||
getModeAtPosition(document: TextDocument, position: Position): LanguageMode | undefined;
|
||||
getModesInRange(document: TextDocument, range: Range): LanguageModeRange[];
|
||||
getAllModes(): LanguageMode[];
|
||||
getAllModesInDocument(document: TextDocument): LanguageMode[];
|
||||
getMode(languageId: string): LanguageMode | undefined;
|
||||
onDocumentRemoved(document: TextDocument): void;
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
export interface LanguageModeRange extends Range {
|
||||
mode: LanguageMode | undefined;
|
||||
attributeValue?: boolean;
|
||||
}
|
||||
|
||||
export function getLanguageModes(supportedLanguages: { [languageId: string]: boolean; }): LanguageModes {
|
||||
|
||||
var htmlLanguageService = getHTMLLanguageService();
|
||||
let documentRegions = getLanguageModelCache<HTMLDocumentRegions>(10, 60, document => getDocumentRegions(htmlLanguageService, document));
|
||||
|
||||
let modelCaches: LanguageModelCache<any>[] = [];
|
||||
modelCaches.push(documentRegions);
|
||||
|
||||
let modes = Object.create(null);
|
||||
modes['html'] = getHTMLMode(htmlLanguageService);
|
||||
if (supportedLanguages['css']) {
|
||||
modes['css'] = getCSSMode(documentRegions);
|
||||
}
|
||||
if (supportedLanguages['javascript']) {
|
||||
modes['javascript'] = getJavascriptMode(documentRegions);
|
||||
}
|
||||
return {
|
||||
getModeAtPosition(document: TextDocument, position: Position): LanguageMode | undefined {
|
||||
let languageId = documentRegions.get(document).getLanguageAtPosition(position);
|
||||
if (languageId) {
|
||||
return modes[languageId];
|
||||
}
|
||||
return void 0;
|
||||
},
|
||||
getModesInRange(document: TextDocument, range: Range): LanguageModeRange[] {
|
||||
return documentRegions.get(document).getLanguageRanges(range).map(r => {
|
||||
return <LanguageModeRange>{
|
||||
start: r.start,
|
||||
end: r.end,
|
||||
mode: r.languageId && modes[r.languageId],
|
||||
attributeValue: r.attributeValue
|
||||
};
|
||||
});
|
||||
},
|
||||
getAllModesInDocument(document: TextDocument): LanguageMode[] {
|
||||
let result = [];
|
||||
for (let languageId of documentRegions.get(document).getLanguagesInDocument()) {
|
||||
let mode = modes[languageId];
|
||||
if (mode) {
|
||||
result.push(mode);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
getAllModes(): LanguageMode[] {
|
||||
let result = [];
|
||||
for (let languageId in modes) {
|
||||
let mode = modes[languageId];
|
||||
if (mode) {
|
||||
result.push(mode);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
getMode(languageId: string): LanguageMode {
|
||||
return modes[languageId];
|
||||
},
|
||||
onDocumentRemoved(document: TextDocument) {
|
||||
modelCaches.forEach(mc => mc.onDocumentRemoved(document));
|
||||
for (let mode in modes) {
|
||||
modes[mode].onDocumentRemoved(document);
|
||||
}
|
||||
},
|
||||
dispose(): void {
|
||||
modelCaches.forEach(mc => mc.dispose());
|
||||
modelCaches = [];
|
||||
for (let mode in modes) {
|
||||
modes[mode].dispose();
|
||||
}
|
||||
modes = {};
|
||||
}
|
||||
};
|
||||
}
|
13
my-snippets/laravel-blade/server/src/utils/arrays.ts
Normal file
13
my-snippets/laravel-blade/server/src/utils/arrays.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
export function pushAll<T>(to: T[], from: T[]) {
|
||||
if (from) {
|
||||
for (var i = 0; i < from.length; i++) {
|
||||
to.push(from[i]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { DocumentContext } from 'vscode-html-languageservice';
|
||||
import { endsWith, startsWith } from '../utils/strings';
|
||||
import * as url from 'url';
|
||||
import { WorkspaceFolder } from 'vscode-languageserver-protocol/lib/protocol.workspaceFolders.proposed';
|
||||
|
||||
export function getDocumentContext(documentUri: string, workspaceFolders: WorkspaceFolder[]): DocumentContext {
|
||||
function getRootFolder(): string | undefined {
|
||||
for (let folder of workspaceFolders) {
|
||||
let folderURI = folder.uri;
|
||||
if (!endsWith(folderURI, '/')) {
|
||||
folderURI = folderURI + '/';
|
||||
}
|
||||
if (startsWith(documentUri, folderURI)) {
|
||||
return folderURI;
|
||||
}
|
||||
}
|
||||
return void 0;
|
||||
}
|
||||
|
||||
return {
|
||||
resolveReference: (ref, base = documentUri) => {
|
||||
if (ref[0] === '/') { // resolve absolute path against the current workspace folder
|
||||
if (startsWith(base, 'file://')) {
|
||||
let folderUri = getRootFolder();
|
||||
if (folderUri) {
|
||||
return folderUri + ref.substr(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return url.resolve(base, ref);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
32
my-snippets/laravel-blade/server/src/utils/edits.ts
Normal file
32
my-snippets/laravel-blade/server/src/utils/edits.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { TextDocument, TextEdit, Position } from 'vscode-languageserver-types';
|
||||
|
||||
export function applyEdits(document: TextDocument, edits: TextEdit[]): string {
|
||||
let text = document.getText();
|
||||
let sortedEdits = edits.sort((a, b) => {
|
||||
let startDiff = comparePositions(a.range.start, b.range.start);
|
||||
if (startDiff === 0) {
|
||||
return comparePositions(a.range.end, b.range.end);
|
||||
}
|
||||
return startDiff;
|
||||
});
|
||||
sortedEdits.forEach(e => {
|
||||
let startOffset = document.offsetAt(e.range.start);
|
||||
let endOffset = document.offsetAt(e.range.end);
|
||||
text = text.substring(0, startOffset) + e.newText + text.substring(endOffset, text.length);
|
||||
});
|
||||
return text;
|
||||
}
|
||||
|
||||
function comparePositions(p1: Position, p2: Position) {
|
||||
let diff = p2.line - p1.line;
|
||||
if (diff === 0) {
|
||||
return p2.character - p1.character;
|
||||
}
|
||||
return diff;
|
||||
}
|
33
my-snippets/laravel-blade/server/src/utils/errors.ts
Normal file
33
my-snippets/laravel-blade/server/src/utils/errors.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
export function formatError(message: string, err: any): string {
|
||||
if (err instanceof Error) {
|
||||
let error = <Error>err;
|
||||
return `${message}: ${error.message}\n${error.stack}`;
|
||||
} else if (typeof err === 'string') {
|
||||
return `${message}: ${err}`;
|
||||
} else if (err) {
|
||||
return `${message}: ${err.toString()}`;
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
export function runSafe<T>(func: () => Thenable<T> | T, errorVal: T, errorMessage: string): Thenable<T> | T {
|
||||
try {
|
||||
let t = func();
|
||||
if (t instanceof Promise) {
|
||||
return t.then(void 0, e => {
|
||||
console.error(formatError(errorMessage, e));
|
||||
return errorVal;
|
||||
});
|
||||
}
|
||||
return t;
|
||||
} catch (e) {
|
||||
console.error(formatError(errorMessage, e));
|
||||
return errorVal;
|
||||
}
|
||||
}
|
79
my-snippets/laravel-blade/server/src/utils/strings.ts
Normal file
79
my-snippets/laravel-blade/server/src/utils/strings.ts
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
export function getWordAtText(text: string, offset: number, wordDefinition: RegExp): { start: number, length: number } {
|
||||
let lineStart = offset;
|
||||
while (lineStart > 0 && !isNewlineCharacter(text.charCodeAt(lineStart - 1))) {
|
||||
lineStart--;
|
||||
}
|
||||
let offsetInLine = offset - lineStart;
|
||||
let lineText = text.substr(lineStart);
|
||||
|
||||
// make a copy of the regex as to not keep the state
|
||||
let flags = wordDefinition.ignoreCase ? 'gi' : 'g';
|
||||
wordDefinition = new RegExp(wordDefinition.source, flags);
|
||||
|
||||
let match = wordDefinition.exec(lineText);
|
||||
while (match && match.index + match[0].length < offsetInLine) {
|
||||
match = wordDefinition.exec(lineText);
|
||||
}
|
||||
if (match && match.index <= offsetInLine) {
|
||||
return { start: match.index + lineStart, length: match[0].length };
|
||||
}
|
||||
|
||||
return { start: offset, length: 0 };
|
||||
}
|
||||
|
||||
export function startsWith(haystack: string, needle: string): boolean {
|
||||
if (haystack.length < needle.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < needle.length; i++) {
|
||||
if (haystack[i] !== needle[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function endsWith(haystack: string, needle: string): boolean {
|
||||
let diff = haystack.length - needle.length;
|
||||
if (diff > 0) {
|
||||
return haystack.indexOf(needle, diff) === diff;
|
||||
} else if (diff === 0) {
|
||||
return haystack === needle;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function repeat(value: string, count: number) {
|
||||
var s = '';
|
||||
while (count > 0) {
|
||||
if ((count & 1) === 1) {
|
||||
s += value;
|
||||
}
|
||||
value += value;
|
||||
count = count >>> 1;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
export function isWhitespaceOnly(str: string) {
|
||||
return /^\s*$/.test(str);
|
||||
}
|
||||
|
||||
export function isEOL(content: string, offset: number) {
|
||||
return isNewlineCharacter(content.charCodeAt(offset));
|
||||
}
|
||||
|
||||
const CR = '\r'.charCodeAt(0);
|
||||
const NL = '\n'.charCodeAt(0);
|
||||
export function isNewlineCharacter(charCode: number) {
|
||||
return charCode === CR || charCode === NL;
|
||||
}
|
14
my-snippets/laravel-blade/server/tsconfig.json
Normal file
14
my-snippets/laravel-blade/server/tsconfig.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"outDir": "./out",
|
||||
"noUnusedLocals": true,
|
||||
"lib": [
|
||||
"es5", "es2015.promise"
|
||||
]
|
||||
},
|
||||
"exclude": [
|
||||
"**/jquery.d.ts"
|
||||
]
|
||||
}
|
49
my-snippets/laravel-blade/snippets/blade.json
Normal file
49
my-snippets/laravel-blade/snippets/blade.json
Normal file
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"Blade-component": {
|
||||
"prefix": "Blade::component",
|
||||
"body": "Blade::component('${1:package-name}', ${2:PackageNameComponent}::class);",
|
||||
"description": "Registering Package Components (AppServiceProvider boot method)"
|
||||
},
|
||||
"Blade-include": {
|
||||
"prefix": "Blade::include",
|
||||
"body": "Blade::include('${1:includes.input}', '${2:input}');",
|
||||
"description": "Aliasing Includes (AppServiceProvider boot method)"
|
||||
},
|
||||
"Blade-if": {
|
||||
"prefix": "Blade::if",
|
||||
"body": [
|
||||
"Blade::if('${1:env}', function ($${2:environment}) {",
|
||||
" ${3:return app()->environment($$environment);}",
|
||||
"});"
|
||||
],
|
||||
"description": "Custom If Statements (AppServiceProvider boot method)"
|
||||
},
|
||||
"Blade-directive": {
|
||||
"prefix": "Blade::directive",
|
||||
"body": [
|
||||
"Blade::directive('${1:datetime}', function ($${2:expression}) {",
|
||||
" ${3:return \"<?php echo ($$expression)->format('m/d/Y H:i'); ?>\";}",
|
||||
"});"
|
||||
],
|
||||
"description": "Custom directive (AppServiceProvider boot method)"
|
||||
},
|
||||
"Blade-stringable": {
|
||||
"prefix": "Blade::stringable",
|
||||
"body": [
|
||||
"Blade::stringable(function (${1:Money} $${2:money}) {",
|
||||
" ${3:return $$money->formatTo('en_GB');}",
|
||||
"});"
|
||||
],
|
||||
"description": "Custom echo handlers (AppServiceProvider boot method)"
|
||||
},
|
||||
"Blade-render": {
|
||||
"prefix": "Blade::render",
|
||||
"body": "Blade::render(${1:'Blade template string'}, ${2:\\$data});",
|
||||
"description": "Transform a raw Blade template string into valid HTML (Laravel 9.x)"
|
||||
},
|
||||
"Blade-renderComponent": {
|
||||
"prefix": "Blade::renderComponent",
|
||||
"body": "Blade::renderComponent(new ${1:HelloComponent}(${2:\\$params}));",
|
||||
"description": "Render a given class component by passing the component instance to the method (Laravel 9.x)"
|
||||
}
|
||||
}
|
62
my-snippets/laravel-blade/snippets/helpers.json
Normal file
62
my-snippets/laravel-blade/snippets/helpers.json
Normal file
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
/* Paths */
|
||||
"Path-elixir": {
|
||||
"prefix": "lv:elixir",
|
||||
"body": "{{ elixir('${1:file}') }}",
|
||||
"description": "(deprecated) elixir path"
|
||||
},
|
||||
"Path-mix": {
|
||||
"prefix": "lv:mix",
|
||||
"body": "{{ mix('${1:file}') }}",
|
||||
"description": "mix path"
|
||||
},
|
||||
/* Strings */
|
||||
"String-trans": {
|
||||
"prefix": "lv:trans",
|
||||
"body": "{{ trans('$1') }}",
|
||||
"description": "trans"
|
||||
},
|
||||
/* URLs */
|
||||
"URL-action": {
|
||||
"prefix": "lv:action",
|
||||
"body": "{{ action('${1:ControllerName}', [${2:'id'=>1}]) }}",
|
||||
"description": "URL-action"
|
||||
},
|
||||
"URL-secure-asset": {
|
||||
"prefix": "lv:secure-asset",
|
||||
"body": "{{ secure_asset('$1', ${2:\\$title}, ${3:\\$attributes=[]}) }}",
|
||||
"description": "URL-secure-asset"
|
||||
},
|
||||
"URL-url": {
|
||||
"prefix": "lv:url",
|
||||
"body": "{{ url('${1:url}', [$2]) }}",
|
||||
"description": "URL-url"
|
||||
},
|
||||
"URL-asset": {
|
||||
"prefix": "lv:asset",
|
||||
"body": "{{ asset('$1') }}",
|
||||
"description": "URL-asset"
|
||||
},
|
||||
"URL-route": {
|
||||
"prefix": "lv:route",
|
||||
"body": "{{ route('${1:routeName}', [${2:'id'=>1}]) }}",
|
||||
"description": "URL-route"
|
||||
},
|
||||
/* Miscellaneous */
|
||||
"Form-csrf-field": {
|
||||
"prefix": "lv:csrf-field",
|
||||
"body": "{{ csrf_field() }}",
|
||||
"description": "CSRF hidden field"
|
||||
},
|
||||
"csrf-token": {
|
||||
"prefix": "lv:csrf-token",
|
||||
"body": "{{ csrf_token() }}",
|
||||
"description": "CSRF token"
|
||||
},
|
||||
/* Paginate */
|
||||
"Paginate-links": {
|
||||
"prefix": "lv:pagination-links",
|
||||
"body": "{{ \\$${1:collection}->links() }}",
|
||||
"description": "pagination links"
|
||||
}
|
||||
}
|
17
my-snippets/laravel-blade/snippets/livewire.json
Normal file
17
my-snippets/laravel-blade/snippets/livewire.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"livewireStyles": {
|
||||
"prefix": "livewire:styles",
|
||||
"body": "@livewireStyles",
|
||||
"description": "Livewire Styles directive"
|
||||
},
|
||||
"livewireScripts": {
|
||||
"prefix": "livewire:scripts",
|
||||
"body": "@livewireScripts",
|
||||
"description": "Livewire Scripts directive"
|
||||
},
|
||||
"livewire-component": {
|
||||
"prefix": "livewire:component",
|
||||
"body": "@livewire('${1:component}', ['${2:user}' => \\$${3:user}]${4:, key(\\$$3->id)})",
|
||||
"description": "Livewire nesting components"
|
||||
}
|
||||
}
|
460
my-snippets/laravel-blade/snippets/snippets.json
Normal file
460
my-snippets/laravel-blade/snippets/snippets.json
Normal file
|
@ -0,0 +1,460 @@
|
|||
{
|
||||
/* Extending a layout */
|
||||
"Extend layout": {
|
||||
"prefix": "b:extends",
|
||||
"body": "@extends('${1:name}')",
|
||||
"description": "extends view layout"
|
||||
},
|
||||
"Yield content": {
|
||||
"prefix": "b:yield",
|
||||
"body": "@yield('${1:name}')",
|
||||
"description": "yield content section"
|
||||
},
|
||||
"Content Section": {
|
||||
"prefix": "b:section",
|
||||
"body": [
|
||||
"@section('${1:name}')",
|
||||
" $2",
|
||||
"@endsection"
|
||||
],
|
||||
"description": "content section"
|
||||
},
|
||||
"Content Section Show": {
|
||||
"prefix": "b:section-show",
|
||||
"body": [
|
||||
"@section('$1')",
|
||||
" $2",
|
||||
"@show"
|
||||
],
|
||||
"description": "content section show"
|
||||
},
|
||||
/* Include sub-view */
|
||||
"Include view": {
|
||||
"prefix": "b:include",
|
||||
"body": "@include('${1:name}')",
|
||||
"description": "include view"
|
||||
},
|
||||
/* If Statements */
|
||||
"If-block": {
|
||||
"prefix": "b:if",
|
||||
"body": [
|
||||
"@if ($1)",
|
||||
" $2",
|
||||
"@endif"
|
||||
],
|
||||
"description": "@if block"
|
||||
},
|
||||
"If-else-block": {
|
||||
"prefix": "b:if-else",
|
||||
"body": [
|
||||
"@if ($1)",
|
||||
" $2",
|
||||
"@else",
|
||||
" $3",
|
||||
"@endif"
|
||||
],
|
||||
"description": "if-else block"
|
||||
},
|
||||
"Has Section": {
|
||||
"prefix": "b:has-section",
|
||||
"body": [
|
||||
"@hasSection ('${1:name}')",
|
||||
" $2",
|
||||
"@else",
|
||||
" $3",
|
||||
"@endif"
|
||||
],
|
||||
"description": "@hasSection condition"
|
||||
},
|
||||
"Unless-block": {
|
||||
"prefix": "b:unless",
|
||||
"body": [
|
||||
"@unless ($1)",
|
||||
" $2",
|
||||
"@endunless"
|
||||
],
|
||||
"description": "@unless block"
|
||||
},
|
||||
/* Loops */
|
||||
"For-block": {
|
||||
"prefix": "b:for",
|
||||
"body": [
|
||||
"@for (\\$i = ${1:0}; \\$i < ${2:\\$count}; \\$i++)",
|
||||
" $3",
|
||||
"@endfor"
|
||||
],
|
||||
"description": "@for block"
|
||||
},
|
||||
"Foreach-block": {
|
||||
"prefix": "b:foreach",
|
||||
"body": [
|
||||
"@foreach (${1:\\$collection} as ${2:\\$item})",
|
||||
" $3",
|
||||
"@endforeach"
|
||||
],
|
||||
"description": "@foreach block"
|
||||
},
|
||||
"forelse-block": {
|
||||
"prefix": "b:forelse",
|
||||
"body": [
|
||||
"@forelse (${1:\\$collection} as ${2:\\$item})",
|
||||
" $3",
|
||||
"@empty",
|
||||
" $4",
|
||||
"@endforelse"
|
||||
],
|
||||
"description": "@forelse block"
|
||||
},
|
||||
"while-block": {
|
||||
"prefix": "b:while",
|
||||
"body": [
|
||||
"@while ($1)",
|
||||
" $2",
|
||||
"@endwhile"
|
||||
],
|
||||
"description": "@while block"
|
||||
},
|
||||
/* Rendering views for collections */
|
||||
"each loop": {
|
||||
"prefix": "b:each",
|
||||
"body": "@each('${1:view.name}', ${2:\\$collection}, '${3:variable}', '${4:view.empty}')",
|
||||
"description": "@each loop"
|
||||
},
|
||||
/* Comments */
|
||||
"blade comment": {
|
||||
"prefix": "b:comment",
|
||||
"body": "{{-- ${1:comment} --}}",
|
||||
"description": "comment block"
|
||||
},
|
||||
/* Display Data */
|
||||
"blade echo-data": {
|
||||
"prefix": "b:echo",
|
||||
"body": "{{ ${1:\\$data} }}",
|
||||
"description": "echo data"
|
||||
},
|
||||
"blade echo-unescaped-data": {
|
||||
"prefix": "b:echo-html",
|
||||
"body": "{!! ${1:\\$html_data} !!}",
|
||||
"description": "echo unescaped data (allow html outputs)"
|
||||
},
|
||||
"blade echo-untouch": {
|
||||
"prefix": "b:echo-raw",
|
||||
"body": "@{{ ${1:variable} }}",
|
||||
"description": "echo untouched data (allow javascript expression)"
|
||||
},
|
||||
"blade verbatim": {
|
||||
"prefix": "b:verbatim",
|
||||
"body": [
|
||||
"@verbatim",
|
||||
"{{ ${1:variable} }}",
|
||||
"@endverbatim"
|
||||
],
|
||||
"description": "displaying JavaScript variables in a large portion of your template"
|
||||
},
|
||||
/* Stacks */
|
||||
"Push stack": {
|
||||
"prefix": "b:push",
|
||||
"body": [
|
||||
"@push('${1:name}')",
|
||||
" $2",
|
||||
"@endpush"
|
||||
],
|
||||
"description": "@push stack"
|
||||
},
|
||||
"Stack": {
|
||||
"prefix": "b:stack",
|
||||
"body": "@stack('${1:name}')",
|
||||
"description": "@stack"
|
||||
},
|
||||
/* Service Injection */
|
||||
"inject service": {
|
||||
"prefix": "b:inject",
|
||||
"body": "@inject('${1:name}', '${2:class}')",
|
||||
"description": "@inject Service"
|
||||
},
|
||||
/* Authorizing */
|
||||
"can": {
|
||||
"prefix": "b:can",
|
||||
"body": [
|
||||
"@can('${1:update}', ${2:\\$post})",
|
||||
" $3",
|
||||
"@endcan"
|
||||
],
|
||||
"description": "display a portion of the page only if the user is authorized to perform a given action."
|
||||
},
|
||||
"can-elsecan": {
|
||||
"prefix": "b:can-elsecan",
|
||||
"body": [
|
||||
"@can('${1:update}', ${2:\\$post})",
|
||||
" $3",
|
||||
"@elsecan('create', App\\Models\\\\${4:Post}::class)",
|
||||
" $5",
|
||||
"@endcan"
|
||||
],
|
||||
"description": "display a portion of the page only if the user is authorized to perform a given action."
|
||||
},
|
||||
"canany": {
|
||||
"prefix": "b:canany",
|
||||
"body": [
|
||||
"@canany(['update', 'view', 'delete'], ${1:\\$post})",
|
||||
" $2",
|
||||
"@endcanany"
|
||||
],
|
||||
"description": "display a portion of the page only if the user is authorized to perform a given action."
|
||||
},
|
||||
"canany-elsecanany": {
|
||||
"prefix": "b:canany-elsecanany",
|
||||
"body": [
|
||||
"@canany(['update', 'view', 'delete'], ${1:\\$post})",
|
||||
" $2",
|
||||
"@elsecanany(['create'], App\\Models\\\\${3:Post}::class)",
|
||||
" $4",
|
||||
"@endcanany"
|
||||
],
|
||||
"description": "display a portion of the page only if the user is authorized to perform a given action."
|
||||
},
|
||||
"cannot": {
|
||||
"prefix": "b:cannot",
|
||||
"body": [
|
||||
"@cannot('${1:update}', ${2:\\$post})",
|
||||
" $3",
|
||||
"@endcannot"
|
||||
],
|
||||
"description": "display a portion of the page only if the user is authorized to perform a given action."
|
||||
},
|
||||
"cannot-elsecannot": {
|
||||
"prefix": "b:cannot-elsecannot",
|
||||
"body": [
|
||||
"@cannot('${1:update}', ${2:\\$post})",
|
||||
" $3",
|
||||
"@elsecannot('create', App\\Models\\\\${5:Post}::class)",
|
||||
" $6",
|
||||
"@endcannot"
|
||||
],
|
||||
"description": "display a portion of the page only if the user is authorized to perform a given action."
|
||||
},
|
||||
/* v5.3 - $loop variable */
|
||||
"loop": {
|
||||
"prefix": "b:loop",
|
||||
"body": [
|
||||
"\\$loop->${1:first}"
|
||||
],
|
||||
"description": "$loop->(index|remaining|count|first|last|depth|parent)"
|
||||
},
|
||||
"loop first": {
|
||||
"prefix": "b:loop-first",
|
||||
"body": [
|
||||
"@if (\\$loop->first)",
|
||||
" ${1:{{-- This is the first iteration --\\}\\}}",
|
||||
"@endif"
|
||||
],
|
||||
"description": "$loop->first"
|
||||
},
|
||||
"loop last": {
|
||||
"prefix": "b:loop-last",
|
||||
"body": [
|
||||
"@if (\\$loop->last)",
|
||||
" ${1:{{-- This is the last iteration --\\}\\}}",
|
||||
"@endif"
|
||||
],
|
||||
"description": "$loop->last"
|
||||
},
|
||||
"php": {
|
||||
"prefix": "b:php",
|
||||
"body": [
|
||||
"@php",
|
||||
" $1",
|
||||
"@endphp"
|
||||
],
|
||||
"description": "@php block code in view"
|
||||
},
|
||||
"includeIf": {
|
||||
"prefix": "b:includeIf",
|
||||
"body": "@includeIf('${1:view.name}'${2:, ['some' => 'data']})",
|
||||
"description": "include a view that may or may not be present, you should use the @includeIf directive"
|
||||
},
|
||||
/* v5.4 */
|
||||
"component": {
|
||||
"prefix": "b:component",
|
||||
"body": [
|
||||
"@component('$1')",
|
||||
" $2",
|
||||
"@endcomponent"
|
||||
],
|
||||
"description": "component"
|
||||
},
|
||||
"slot": {
|
||||
"prefix": "b:slot",
|
||||
"body": [
|
||||
"@slot('$1')",
|
||||
" $2",
|
||||
"@endslot"
|
||||
],
|
||||
"description": "slot"
|
||||
},
|
||||
"isset": {
|
||||
"prefix": "b:isset",
|
||||
"body": [
|
||||
"@isset(${1:\\$record})",
|
||||
" $2",
|
||||
"@endisset"
|
||||
],
|
||||
"description": "isset"
|
||||
},
|
||||
"empty": {
|
||||
"prefix": "b:empty",
|
||||
"body": [
|
||||
"@empty(${1:\\$record})",
|
||||
" $2",
|
||||
"@endempty"
|
||||
],
|
||||
"description": "empty"
|
||||
},
|
||||
"error": {
|
||||
"prefix": "b:error",
|
||||
"body": [
|
||||
"@error('${1:record}')",
|
||||
" $2",
|
||||
"@enderror"
|
||||
],
|
||||
"description": "error"
|
||||
},
|
||||
"includeWhen": {
|
||||
"prefix": "b:includeWhen",
|
||||
"body": "@includeWhen(${1:\\$boolean}, '${2:view.name}', [${3:'some' => 'data'}])",
|
||||
"description": "includeWhen"
|
||||
},
|
||||
/* v5.5 */
|
||||
"auth": {
|
||||
"prefix": "b:auth",
|
||||
"body": [
|
||||
"@auth",
|
||||
" $1",
|
||||
"@endauth"
|
||||
],
|
||||
"description": "auth"
|
||||
},
|
||||
"guest": {
|
||||
"prefix": "b:guest",
|
||||
"body": [
|
||||
"@guest",
|
||||
" $1",
|
||||
"@endguest"
|
||||
],
|
||||
"description": "guest"
|
||||
},
|
||||
"switch": {
|
||||
"prefix": "b:switch",
|
||||
"body": [
|
||||
"@switch(${1:\\$type})",
|
||||
" @case(${2:1})",
|
||||
" $3",
|
||||
" @break",
|
||||
" @case(${4:2})",
|
||||
" $5",
|
||||
" @break",
|
||||
" @default",
|
||||
" $6",
|
||||
"@endswitch"
|
||||
],
|
||||
"description": "switch"
|
||||
},
|
||||
"includeFirst": {
|
||||
"prefix": "b:includeFirst",
|
||||
"body": "@includeFirst(['${1:view.name}', '${2:variable}'], [${3:'some' => 'data'}])",
|
||||
"description": "includeFirst"
|
||||
},
|
||||
/* v5.6 */
|
||||
"csrf": {
|
||||
"prefix": "b:csrf",
|
||||
"body": "@csrf",
|
||||
"description": "form csrf field"
|
||||
},
|
||||
"method": {
|
||||
"prefix": "b:method",
|
||||
"body": "@method($1)",
|
||||
"description": "form method field"
|
||||
},
|
||||
"dump": {
|
||||
"prefix": "b:dump",
|
||||
"body": "@dump($1)",
|
||||
"description": "dump"
|
||||
},
|
||||
/* Retrieving Translation Strings */
|
||||
"lang": {
|
||||
"prefix": "b:lang",
|
||||
"body": "@lang('${1:messages.welcome}')",
|
||||
"description": "lang"
|
||||
},
|
||||
/* v6.x */
|
||||
"includeUnless": {
|
||||
"prefix": "b:includeUnless",
|
||||
"body": "@includeUnless(${1:\\$boolean}, '${2:view.name}', [${3:'some' => 'data'}])",
|
||||
"description": "includeUnless"
|
||||
},
|
||||
/* v7.x */
|
||||
"props": {
|
||||
"prefix": "b:props",
|
||||
"body": "@props(['${1:propName}'])",
|
||||
"description": "Blade component data properties"
|
||||
},
|
||||
"env": {
|
||||
"prefix": "b:env",
|
||||
"body": [
|
||||
"@env('${1:staging}')",
|
||||
" $2",
|
||||
"@endenv"
|
||||
],
|
||||
"description": "env"
|
||||
},
|
||||
"production": {
|
||||
"prefix": "b:production",
|
||||
"body": [
|
||||
"@production",
|
||||
" $1",
|
||||
"@endproduction"
|
||||
],
|
||||
"description": "production"
|
||||
},
|
||||
"once": {
|
||||
"prefix": "b:once",
|
||||
"body": [
|
||||
"@once",
|
||||
" $1",
|
||||
"@endonce"
|
||||
],
|
||||
"description": "define a portion of template that will only be evaluated once per rendering cycle"
|
||||
},
|
||||
/* v8.x */
|
||||
"aware": {
|
||||
"prefix": "b:aware",
|
||||
"body": "@aware(['${1:propName}'])",
|
||||
"description": "Accessing data from a parent component (Laravel 8.64)"
|
||||
},
|
||||
"js": {
|
||||
"prefix": "b:js",
|
||||
"body": "@js(${1:\\$data})",
|
||||
"description": "This directive is useful to properly escape JSON within HTML quotes"
|
||||
},
|
||||
"class": {
|
||||
"prefix": "b:class",
|
||||
"body": "@class(['${1:p-4}', ${2:'font-bold' => true}])",
|
||||
"description": "conditionally compiles a CSS class string. (Laravel 8.51)"
|
||||
},
|
||||
/* v9.x */
|
||||
"checked": {
|
||||
"prefix": "b:checked",
|
||||
"body": "@checked(${1:true})",
|
||||
"description": "This directive will echo checked if the provided condition evaluates to true (Laravel 9.x)"
|
||||
},
|
||||
"selected": {
|
||||
"prefix": "b:selected",
|
||||
"body": "@selected(${1:true})",
|
||||
"description": "The @selected directive may be used to indicate if a given select option should be \"selected\" (Laravel 9.x)"
|
||||
},
|
||||
"disabled": {
|
||||
"prefix": "b:disabled",
|
||||
"body": "@disabled(${1:true})",
|
||||
"description": "The @disabled directive may be used to indicate if a given element should be \"disabled\" (Laravel 9.x)"
|
||||
}
|
||||
}
|
87
my-snippets/laravel-blade/src/extension.ts
Normal file
87
my-snippets/laravel-blade/src/extension.ts
Normal file
|
@ -0,0 +1,87 @@
|
|||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import * as html from 'vscode-html-languageservice';
|
||||
import * as lst from 'vscode-languageserver-types';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { BladeFormattingEditProvider } from './providers/BladeFormattingEditProvider';
|
||||
import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind, RequestType, TextDocumentPositionParams } from 'vscode-languageclient';
|
||||
|
||||
const service = html.getLanguageService()
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
class DocumentHighlight implements vscode.DocumentHighlightProvider
|
||||
{
|
||||
provideDocumentHighlights(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): vscode.DocumentHighlight[] | Thenable<vscode.DocumentHighlight[]> {
|
||||
let doc = lst.TextDocument.create(document.uri.fsPath, 'html', 1, document.getText());
|
||||
return (service.findDocumentHighlights(doc, position, service.parseHTMLDocument(doc)) as any);
|
||||
}
|
||||
} // DocumentHighlight
|
||||
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
|
||||
let documentSelector: vscode.DocumentSelector = {
|
||||
language: 'blade'
|
||||
};
|
||||
|
||||
context.subscriptions.push(vscode.languages.registerDocumentHighlightProvider(documentSelector, new DocumentHighlight));
|
||||
|
||||
let bladeFormatCfg = vscode.workspace.getConfiguration('blade.format');
|
||||
if (bladeFormatCfg.get<boolean>('enable')) {
|
||||
context.subscriptions.push(vscode.languages.registerDocumentFormattingEditProvider(documentSelector, new BladeFormattingEditProvider));
|
||||
context.subscriptions.push(vscode.languages.registerDocumentRangeFormattingEditProvider(documentSelector, new BladeFormattingEditProvider));
|
||||
}
|
||||
|
||||
// Set html indent
|
||||
const EMPTY_ELEMENTS: string[] = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'];
|
||||
vscode.languages.setLanguageConfiguration('blade', {
|
||||
indentationRules: {
|
||||
increaseIndentPattern: /<(?!\?|(?:area|base|br|col|frame|hr|html|img|input|link|meta|param)\b|[^>]*\/>)([-_\.A-Za-z0-9]+)(?=\s|>)\b[^>]*>(?!.*<\/\1>)|<!--(?!.*-->)|\{[^}"']*$/,
|
||||
decreaseIndentPattern: /^\s*(<\/(?!html)[-_\.A-Za-z0-9]+\b[^>]*>|-->|\})/
|
||||
},
|
||||
wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g,
|
||||
onEnterRules: [
|
||||
{
|
||||
beforeText: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join('|')}))([_:\\w][_:\\w-.\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'),
|
||||
afterText: /^<\/([_:\w][_:\w-.\d]*)\s*>$/i,
|
||||
action: { indentAction: vscode.IndentAction.IndentOutdent }
|
||||
},
|
||||
{
|
||||
beforeText: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join('|')}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'),
|
||||
action: { indentAction: vscode.IndentAction.Indent }
|
||||
}
|
||||
],
|
||||
});
|
||||
|
||||
// The server is implemented in node
|
||||
let serverModule = context.asAbsolutePath(path.join('server', 'out', 'htmlServerMain.js'));
|
||||
// The debug options for the server
|
||||
let debugOptions = { execArgv: ['--nolazy', '--inspect=6045'] };
|
||||
|
||||
// If the extension is launch in debug mode the debug server options are use
|
||||
// Otherwise the run options are used
|
||||
let serverOptions: ServerOptions = {
|
||||
run: { module: serverModule, transport: TransportKind.ipc },
|
||||
debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions }
|
||||
};
|
||||
|
||||
let embeddedLanguages = { css: true, javascript: true };
|
||||
// Options to control the language client
|
||||
let clientOptions: LanguageClientOptions = {
|
||||
documentSelector: ['blade'],
|
||||
synchronize: {
|
||||
configurationSection: ['blade', 'css', 'javascript', 'emmet'], // the settings to synchronize
|
||||
},
|
||||
initializationOptions: {
|
||||
embeddedLanguages
|
||||
}
|
||||
};
|
||||
|
||||
// Create the language client and start the client.
|
||||
let client = new LanguageClient('blade', localize('bladeserver.name', 'BLADE Language Server'), serverOptions, clientOptions);
|
||||
client.registerProposedFeatures();
|
||||
context.subscriptions.push(client.start());
|
||||
}
|
||||
|
||||
export function deactivate() {
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
import * as vscode from 'vscode';
|
||||
import * as html from 'vscode-html-languageservice';
|
||||
import * as lst from 'vscode-languageserver-types';
|
||||
import { BladeFormatter, IBladeFormatterOptions } from "../services/BladeFormatter";
|
||||
|
||||
const service = html.getLanguageService()
|
||||
|
||||
export class BladeFormattingEditProvider implements vscode.DocumentFormattingEditProvider, vscode.DocumentRangeFormattingEditProvider
|
||||
{
|
||||
formatterOptions: IBladeFormatterOptions;
|
||||
|
||||
provideDocumentFormattingEdits(document: vscode.TextDocument, options: vscode.FormattingOptions): vscode.TextEdit[] {
|
||||
let range = new vscode.Range(new vscode.Position(0, 0), new vscode.Position((document.lineCount - 1), Number.MAX_VALUE));
|
||||
return this.provideFormattingEdits(document, document.validateRange(range), options);
|
||||
}
|
||||
|
||||
provideDocumentRangeFormattingEdits(document: vscode.TextDocument, range: vscode.Range, options: vscode.FormattingOptions): vscode.TextEdit[] {
|
||||
return this.provideFormattingEdits(document, range, options);
|
||||
}
|
||||
|
||||
private provideFormattingEdits(document: vscode.TextDocument, range: vscode.Range, options: vscode.FormattingOptions): vscode.TextEdit[] {
|
||||
|
||||
this.formatterOptions = {
|
||||
tabSize: options.tabSize,
|
||||
insertSpaces: options.insertSpaces
|
||||
};
|
||||
|
||||
// Mapping HTML format options
|
||||
let htmlFormatConfig = vscode.workspace.getConfiguration('html.format');
|
||||
Object.assign(options, htmlFormatConfig);
|
||||
|
||||
// format as html
|
||||
let doc = lst.TextDocument.create(document.uri.fsPath, 'html', 1, document.getText());
|
||||
let htmlTextEdit = service.format(doc, range, options);
|
||||
|
||||
// format as blade
|
||||
let formatter = new BladeFormatter(this.formatterOptions);
|
||||
let bladeText = formatter.format(htmlTextEdit[0].newText);
|
||||
|
||||
return [vscode.TextEdit.replace(range, bladeText)];
|
||||
}
|
||||
}
|
34
my-snippets/laravel-blade/src/services/BladeFormatter.ts
Normal file
34
my-snippets/laravel-blade/src/services/BladeFormatter.ts
Normal file
|
@ -0,0 +1,34 @@
|
|||
export class BladeFormatter
|
||||
{
|
||||
newLine: string = "\n";
|
||||
indentPattern: string;
|
||||
|
||||
constructor(options?: IBladeFormatterOptions) {
|
||||
options = options || {};
|
||||
|
||||
// options default value
|
||||
options.tabSize = options.tabSize || 4;
|
||||
if (typeof options.insertSpaces === "undefined") {
|
||||
options.insertSpaces = true;
|
||||
}
|
||||
|
||||
this.indentPattern = (options.insertSpaces) ? " ".repeat(options.tabSize) : "\t";
|
||||
}
|
||||
|
||||
format(inuptText: string): string {
|
||||
|
||||
let inComment: boolean = false;
|
||||
let output: string = inuptText;
|
||||
|
||||
// fix #57 url extra space after formatting
|
||||
output = output.replace(/url\(\"(\s*)/g, "url\(\"");
|
||||
|
||||
return output.trim();
|
||||
}
|
||||
}
|
||||
|
||||
export interface IBladeFormatterOptions
|
||||
{
|
||||
insertSpaces?: boolean;
|
||||
tabSize?: number;
|
||||
}
|
3902
my-snippets/laravel-blade/syntaxes/blade.tmLanguage.json
Normal file
3902
my-snippets/laravel-blade/syntaxes/blade.tmLanguage.json
Normal file
File diff suppressed because one or more lines are too long
517
my-snippets/laravel-blade/tests/test.blade.php
Normal file
517
my-snippets/laravel-blade/tests/test.blade.php
Normal file
|
@ -0,0 +1,517 @@
|
|||
<h1>Blade Syntax Highlighting Tests</h1>
|
||||
|
||||
{{-- Displaying Data --}}
|
||||
Hello, {{ $name }}.
|
||||
The current UNIX timestamp is {{ time() }}.
|
||||
|
||||
{{-- Escape Data --}}
|
||||
Hello, {{{ $name }}}.
|
||||
|
||||
{{-- Echoing Data If It Exists --}}
|
||||
{{ isset($name) ? $name : 'Default' }}
|
||||
{{ $name or 'Default' }}
|
||||
|
||||
<div class="{{ $name }}" {{ isset($name) ? $name : 'Default' }}></div>
|
||||
|
||||
{{-- Displaying Unescaped Data --}}
|
||||
Hello, {!! $name !!}.
|
||||
|
||||
{{-- Rendering JSON --}}
|
||||
<script>
|
||||
var app = @json($array);
|
||||
var app = @json($array, JSON_PRETTY_PRINT);
|
||||
</script>
|
||||
|
||||
{{-- Blade & JavaScript Frameworks --}}
|
||||
Hello, @{{ name }}.
|
||||
|
||||
{{-- Blade --}}
|
||||
@@json()
|
||||
|
||||
<!-- HTML output -->
|
||||
@json()
|
||||
|
||||
@verbatim
|
||||
<div class="container">
|
||||
Hello, {{ name }}.
|
||||
</div>
|
||||
@endverbatim
|
||||
|
||||
{{-- Control Structures --}}
|
||||
|
||||
{{-- If Statements --}}
|
||||
@if (count($records) === 1)
|
||||
I have one record!
|
||||
@elseif (count($records) > 1)
|
||||
I have multiple records!
|
||||
@else
|
||||
I don't have any records!
|
||||
@endif
|
||||
|
||||
@unless (Auth::check())
|
||||
You are not signed in.
|
||||
@endunless
|
||||
|
||||
|
||||
@isset($records)
|
||||
// $records is defined and is not null...
|
||||
@endisset
|
||||
|
||||
@empty($records)
|
||||
// $records is "empty"...
|
||||
@endempty
|
||||
|
||||
|
||||
{{-- Authentication Directives --}}
|
||||
|
||||
@auth
|
||||
// The user is authenticated...
|
||||
@endauth
|
||||
|
||||
@guest
|
||||
// The user is not authenticated...
|
||||
@endguest
|
||||
|
||||
@auth('admin')
|
||||
// The user is authenticated...
|
||||
@endauth
|
||||
|
||||
@guest('admin')
|
||||
// The user is not authenticated...
|
||||
@endguest
|
||||
|
||||
|
||||
{{-- Section Directives --}}
|
||||
|
||||
@hasSection('navigation')
|
||||
<div class="pull-right">
|
||||
@yield('navigation')
|
||||
</div>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
@endif
|
||||
|
||||
@sectionMissing('navigation')
|
||||
<div class="pull-right">
|
||||
@include('default-navigation')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
{{-- Environment Directives --}}
|
||||
|
||||
@production
|
||||
// Production specific content...
|
||||
@endproduction
|
||||
|
||||
@env('staging')
|
||||
// The application is running in "staging"...
|
||||
@endenv
|
||||
|
||||
@env(['staging', 'production'])
|
||||
// The application is running in "staging" or "production"...
|
||||
@endenv
|
||||
|
||||
|
||||
{{-- Section Directives --}}
|
||||
|
||||
@hasSection('navigation')
|
||||
<div class="pull-right">
|
||||
@yield('navigation')
|
||||
</div>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
@endif
|
||||
|
||||
@sectionMissing('navigation')
|
||||
<div class="pull-right">
|
||||
@include('default-navigation')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
{{-- Switch Statements --}}
|
||||
|
||||
@switch($i)
|
||||
@case(1)
|
||||
First case...
|
||||
@break
|
||||
|
||||
@case(2)
|
||||
Second case...
|
||||
@break
|
||||
|
||||
@default
|
||||
Default case...
|
||||
@endswitch
|
||||
|
||||
|
||||
{{-- Loops --}}
|
||||
|
||||
@for ($i = 0; $i < 10; $i++)
|
||||
The current value is {{ $i }}
|
||||
@endfor
|
||||
|
||||
@foreach ($users as $user)
|
||||
<p>This is user {{ $user->id }}</p>
|
||||
@endforeach
|
||||
|
||||
@forelse ($users as $user)
|
||||
<li>{{ $user->name }}</li>
|
||||
@empty
|
||||
<p>No users</p>
|
||||
@endforelse
|
||||
|
||||
@while (true)
|
||||
<p>I'm looping forever.</p>
|
||||
@endwhile
|
||||
|
||||
{{-- continue & break --}}
|
||||
@foreach ($users as $user)
|
||||
|
||||
@if ($user->type == 1)
|
||||
@continue
|
||||
@endif
|
||||
|
||||
<li>{{ $user->name }}</li>
|
||||
|
||||
@if ($user->number == 5)
|
||||
@break
|
||||
@endif
|
||||
|
||||
@continue($user->type == 1)
|
||||
<li>{{ $user->name }}</li>
|
||||
@break($user->number == 5)
|
||||
|
||||
@endforeach
|
||||
|
||||
@foreach ($users as $user)
|
||||
@continue($user->type == 1)
|
||||
|
||||
<li>{{ $user->name }}</li>
|
||||
|
||||
@break($user->number == 5)
|
||||
@endforeach
|
||||
|
||||
|
||||
{{-- The Loop Variable --}}
|
||||
|
||||
@foreach ($users as $user)
|
||||
@if ($loop->first)
|
||||
This is the first iteration.
|
||||
@endif
|
||||
|
||||
@if ($loop->last)
|
||||
This is the last iteration.
|
||||
@endif
|
||||
|
||||
<p>This is user {{ $user->id }}</p>
|
||||
|
||||
{{-- $loop->parent --}}
|
||||
@foreach ($user->posts as $post)
|
||||
@if ($loop->parent->first)
|
||||
This is the first iteration of the parent loop.
|
||||
@endif
|
||||
@endforeach
|
||||
@endforeach
|
||||
|
||||
|
||||
{{-- Loop Variables --}}
|
||||
|
||||
{{-- The index of the current loop iteration (starts at 0) --}}
|
||||
{{ $loop->index }}
|
||||
{{-- The current loop iteration (starts at 1) --}}
|
||||
{{ $loop->iteration }}
|
||||
{{-- The iteration remaining in the loop --}}
|
||||
{{ $loop->remaining }}
|
||||
{{-- The total number of items in the array being iterated --}}
|
||||
{{ $loop->count }}
|
||||
{{-- Whether this is the first iteration through the loop --}}
|
||||
{{ $loop->first }}
|
||||
{{-- Whether this is the last iteration through the loop --}}
|
||||
{{ $loop->last }}
|
||||
{{-- The nesting level of the current loop --}}
|
||||
{{ $loop->depth }}
|
||||
{{-- When in a nested loop, the parent's loop variable --}}
|
||||
{{ $loop->parent }}
|
||||
|
||||
@endforeach
|
||||
|
||||
{{-- Comments --}}
|
||||
{{-- This comment will not be present in the rendered HTML --}}
|
||||
|
||||
{{--
|
||||
This comment will not be in the rendered HTML
|
||||
This comment will not be in the rendered HTML
|
||||
This comment will not be in the rendered HTML
|
||||
--}}
|
||||
|
||||
{{-- PHP --}}
|
||||
<?php echo $name; ?>
|
||||
<?= $name; ?>
|
||||
<?php echo ($var)->format('m/d/Y H:i'); ?>
|
||||
|
||||
<?php
|
||||
foreach (range(1, 10) as $number) {
|
||||
echo $number;
|
||||
}
|
||||
?>
|
||||
|
||||
@php ($hello = "hello world")
|
||||
|
||||
@php
|
||||
foreach (range(1, 10) as $number) {
|
||||
echo $number;
|
||||
}
|
||||
@endphp
|
||||
|
||||
|
||||
{{-- Conditional Classes : `@class` directive --}}
|
||||
|
||||
@php
|
||||
$isActive = false;
|
||||
$hasError = true;
|
||||
@endphp
|
||||
|
||||
<span @class([
|
||||
'p-4',
|
||||
'font-bold' => $isActive,
|
||||
'text-gray-500' => ! $isActive,
|
||||
'bg-red' => $hasError,
|
||||
])></span>
|
||||
|
||||
<span class="p-4 text-gray-500 bg-red"></span>
|
||||
|
||||
|
||||
{{-- The @once Directive --}}
|
||||
|
||||
@once
|
||||
@push('scripts')
|
||||
<script>
|
||||
// Your custom JavaScript...
|
||||
</script>
|
||||
@endpush
|
||||
@endonce
|
||||
|
||||
{{-- Forms --}}
|
||||
<form method="POST" action="/foo/bar">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
</form>
|
||||
|
||||
{{-- Validation Errors --}}
|
||||
|
||||
<label for="title">Post Title</label>
|
||||
|
||||
<input id="title" type="text" class="@error('title') is-invalid @enderror">
|
||||
|
||||
@error('title')
|
||||
<div class="alert alert-danger">{{ $message }}</div>
|
||||
@enderror
|
||||
|
||||
|
||||
{{-- Components --}}
|
||||
<x-package-alert />
|
||||
<x-nightshade::calendar />
|
||||
<x-nightshade::color-picker />
|
||||
<x-inputs.button />
|
||||
<x-test></x-test>
|
||||
<x-alert type="error" :message="$message"/>
|
||||
<x-dynamic-component :component="$componentName" class="mt-4" />
|
||||
|
||||
{{-- Component attribute expressions --}}
|
||||
<x-test
|
||||
str="empty"
|
||||
:null="null"
|
||||
:bool-t="true"
|
||||
:bool-f="false"
|
||||
:num-dec-a="1234"
|
||||
:num-dec-b="12_34"
|
||||
:num-dec-c="0123"
|
||||
:num-hex="0x1A"
|
||||
:num-bin="0b101"
|
||||
:num-float-a="1.234"
|
||||
:num-float-b="1.2e3"
|
||||
:num-float-c="7E-10"
|
||||
:num-float-d="1_234.567"
|
||||
:expr-math-a="true + -2 - (3 * 40) / 5 % 6 ^ '7' ** $a"
|
||||
:expr-bit="$a & $b | $a ^ $b << $a >> $b"
|
||||
:expr-str="1 . 'test' . '\\' . $a . true"
|
||||
:expr-arr="[] + []"
|
||||
:expr-func-call="func()"
|
||||
:expr-func-arrow="fn($a) => $a"
|
||||
:expr-cond="$a ? !$b : $c || $a ?: $b || $a ?? $b and $a or $a xor $b"
|
||||
:expr-comp-a="$a == $b"
|
||||
:expr-comp-b="$a === $b"
|
||||
:expr-comp-c="$a != $b"
|
||||
:expr-comp-d="$a <> $b"
|
||||
:expr-comp-e="$a !== $b"
|
||||
:expr-comp-f="$a < $b"
|
||||
:expr-comp-g="$a > $b"
|
||||
:expr-comp-h="$a >= $b"
|
||||
:expr-comp-i="$a <= $b"
|
||||
:expr-comp-j="$a <=> $b"
|
||||
:expr-type="$a instanceof MyClass"
|
||||
:expr-class-a="new MyClass()"
|
||||
:expr-class-b="(new MyClass())->prop"
|
||||
:expr-class-c="(new MyClass())->do()"
|
||||
:expr-class-d="MyClass::class"
|
||||
:expr-class-e="MyClass::$prop"
|
||||
:expr-class-f="MyClass::do()"
|
||||
:expr-class-g="$this->prop"
|
||||
:expr-class-h="$this->do()"
|
||||
:expr-class-i="$instance->prop"
|
||||
:expr-class-j="$instance->do()"
|
||||
:arr="['valueA', true, 0 => 'valueB', 'keyC' => 'valueC']"
|
||||
/>
|
||||
|
||||
|
||||
{{-- Including Sub-Views --}}
|
||||
<div>
|
||||
@include('shared.errors')
|
||||
<form>
|
||||
<!-- Form Contents -->
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@include('view.name')
|
||||
@include('view.name', ['some' => 'data'])
|
||||
@includeIf('view.name', ['some' => 'data'])
|
||||
@includeWhen($boolean, 'view.name', ['some' => 'data'])
|
||||
@includeUnless($boolean, 'view.name', ['some' => 'data'])
|
||||
@includeFirst(['custom.admin', 'admin'], ['some' => 'data'])
|
||||
|
||||
{{-- Rendering Views For Collections --}}
|
||||
@each('view.name', $jobs, 'job')
|
||||
@each('view.name', $jobs, 'job', 'view.empty')
|
||||
|
||||
{{-- Stacks --}}
|
||||
@push('scripts')
|
||||
<script src="/example.js"></script>
|
||||
@endpush
|
||||
|
||||
@stack('scripts')
|
||||
|
||||
@prepend('scripts')
|
||||
This will be first...
|
||||
@endprepend
|
||||
|
||||
{{-- Service Injection --}}
|
||||
@inject('metrics', 'App\Services\MetricsService')
|
||||
<div>
|
||||
Monthly Revenue: {{ $metrics->monthlyRevenue() }}.
|
||||
</div>
|
||||
|
||||
|
||||
{{-- Retrieving Translation Strings --}}
|
||||
@lang('messages.welcome')
|
||||
|
||||
{{-- 5.3 --}}
|
||||
{{ trans('messages.welcome') }}
|
||||
{{-- 5.4 --}}
|
||||
{{ __('messages.welcome') }}
|
||||
|
||||
{{-- Pluralization --}}
|
||||
@choice('messages.apples', 10)
|
||||
|
||||
{{-- 'apples' => '{0} There are none|[1,19] There are some|[20,Inf] There are many', --}}
|
||||
{{ trans_choice('messages.apples', 10) }}
|
||||
|
||||
{{-- Replacing Parameters In Translation Strings --}}
|
||||
{{-- 'greeting' => 'Welcome, :name', --}}
|
||||
{{ __('messages.greeting', ['name' => 'Winnie']) }}
|
||||
|
||||
|
||||
{{-- Authorizing --}}
|
||||
|
||||
@can('update', $post)
|
||||
<!-- The Current User Can Update The Post -->
|
||||
@elsecan('create', App\Models\Post::class)
|
||||
<!-- The Current User Can Create New Post -->
|
||||
@endcan
|
||||
|
||||
@canany(['update'], $post)
|
||||
<!-- The Current User Can Update The Post -->
|
||||
@elsecanany(['create'], App\Models\Post::class)
|
||||
<!-- The Current User Can Create New Post -->
|
||||
@endcanany
|
||||
|
||||
@cannot('update', $post)
|
||||
<!-- The Current User Can't Update The Post -->
|
||||
@elsecannot('create', App\Models\Post::class)
|
||||
<!-- The Current User Can't Create New Post -->
|
||||
@endcannot
|
||||
|
||||
@if (Auth::user()->can('update', $post))
|
||||
<!-- The Current User Can Update The Post -->
|
||||
@endif
|
||||
|
||||
@unless (Auth::user()->can('update', $post))
|
||||
<!-- The Current User Can't Update The Post -->
|
||||
@endunless
|
||||
|
||||
@can('create', App\Models\Post::class)
|
||||
<!-- The Current User Can Create Posts -->
|
||||
@endcan
|
||||
|
||||
@canany(['create'], App\Models\Post::class)
|
||||
<!-- The Current User Can Create Posts -->
|
||||
@endcanany
|
||||
|
||||
@cannot('create', App\Models\Post::class)
|
||||
<!-- The Current User Can't Create Posts -->
|
||||
@endcannot
|
||||
|
||||
{{-- Retrieving Translation Strings --}}
|
||||
|
||||
{{ __('messages.welcome') }}
|
||||
@lang('messages.welcome')
|
||||
|
||||
@props(['type' => 'info', 'message'])
|
||||
|
||||
|
||||
{{-- Envoy --}}
|
||||
|
||||
@setup
|
||||
require __DIR__.'/vendor/autoload.php';
|
||||
$dotenv = new Dotenv\Dotenv(__DIR__);
|
||||
@endsetup
|
||||
|
||||
@servers(['web' => $server])
|
||||
|
||||
@task('init')
|
||||
if [ ! -d {{ $path }}/current ]; then
|
||||
cd {{ $path }}
|
||||
@endtask
|
||||
|
||||
@story('deploy')
|
||||
deployment_start
|
||||
deployment_composer
|
||||
deployment_finish
|
||||
@endstory
|
||||
|
||||
{{-- Livewire --}}
|
||||
|
||||
@livewireStyles
|
||||
@livewireScripts
|
||||
|
||||
@livewire('user-profile', ['user' => $user], key($user->id))
|
||||
|
||||
{{-- Checked / Selected / Disabled Blade Directives (9.x) --}}
|
||||
|
||||
<input type="checkbox"
|
||||
name="active"
|
||||
value="active"
|
||||
@checked(old('active', $user->active)) />
|
||||
|
||||
<select name="version">
|
||||
@foreach ($product->versions as $version)
|
||||
<option value="{{ $version }}" @selected(old('version') == $version)>
|
||||
{{ $version }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<button type="submit" @disabled($errors->isNotEmpty())>
|
||||
Submit
|
||||
</button>
|
17
my-snippets/laravel-blade/tsconfig.json
Normal file
17
my-snippets/laravel-blade/tsconfig.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es6",
|
||||
"outDir": "out",
|
||||
"lib": [
|
||||
"es6"
|
||||
],
|
||||
"sourceMap": true,
|
||||
"rootDir": ".",
|
||||
"skipLibCheck": true,
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"exclude": [
|
||||
"server"
|
||||
]
|
||||
}
|
37
my-snippets/laravel-blade/webpack.config.js
Normal file
37
my-snippets/laravel-blade/webpack.config.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
//@ts-check
|
||||
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
|
||||
/**@type {import('webpack').Configuration}*/
|
||||
const config = {
|
||||
target: 'node',
|
||||
entry: './src/extension.ts',
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'out'),
|
||||
filename: 'extension.js',
|
||||
libraryTarget: 'commonjs2'
|
||||
},
|
||||
devtool: 'source-map',
|
||||
externals: {
|
||||
vscode: 'commonjs vscode'
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.js']
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ts$/,
|
||||
exclude: /node_modules/,
|
||||
use: [
|
||||
{
|
||||
loader: 'ts-loader'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
module.exports = config;
|
Loading…
Add table
Add a link
Reference in a new issue