Skip to content

Commit

Permalink
Merge pull request #629 from kkoomen/feature/svelte
Browse files Browse the repository at this point in the history
[Feature] add support for Svelte
  • Loading branch information
kkoomen authored Oct 1, 2023
2 parents c6fdddb + a6d9e28 commit 395e4ef
Show file tree
Hide file tree
Showing 13 changed files with 288 additions and 3 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
vim-version: [v7.4.2119, v8.2.5172, v9.0.1500]
vim-version: [v8.2.5172, v9.0.1500]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout kkoomen/vim-doge
Expand Down Expand Up @@ -54,7 +54,7 @@ jobs:
fail-fast: false
matrix:
os: [windows-latest]
vim-version: [v8.2.5172, head]
vim-version: [v8.2.5172, v9.0.1500]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout kkoomen/vim-doge
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ Is your favorite doc standard not supported?
| :white_check_mark: | PHP | [phpdoc][phpdoc] |
| :white_check_mark: | JavaScript (Including: ES6, FlowJS and NodeJS) | [JSDoc][jsdoc] |
| :white_check_mark: | TypeScript | [JSDoc][jsdoc] |
| :white_check_mark: | Svelte | [JSDoc][jsdoc] |
| :white_check_mark: | Lua | [LDoc][ldoc] |
| :white_check_mark: | Java | [JavaDoc][javadoc] |
| :white_check_mark: | Groovy | [JavaDoc][javadoc] |
Expand Down Expand Up @@ -164,6 +165,7 @@ Here is the full list of available doc standards per filetype:
| `g:doge_doc_standard_python` | `'reST'` | `'reST'`, `'numpy'`, `'google'`, `'sphinx'` |
| `g:doge_doc_standard_php` | `'phpdoc'` | `'phpdoc'` |
| `g:doge_doc_standard_javascript` | `'jsdoc'` | `'jsdoc'` |
| `g:doge_doc_standard_svelte` | `'jsdoc'` | `'jsdoc'` |
| `g:doge_doc_standard_lua` | `'ldoc'` | `'ldoc'` |
| `g:doge_doc_standard_java` | `'javadoc'` | `'javadoc'` |
| `g:doge_doc_standard_groovy` | `'javadoc'` | `'javadoc'` |
Expand Down
11 changes: 11 additions & 0 deletions ftplugin/svelte.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
let s:save_cpo = &cpoptions
set cpoptions&vim

let b:doge_parser = 'svelte'
let b:doge_insert = 'above'

let b:doge_supported_doc_standards = ['jsdoc']
let b:doge_doc_standard = doge#buffer#get_doc_standard('svelte')

let &cpoptions = s:save_cpo
unlet s:save_cpo
10 changes: 10 additions & 0 deletions helper/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions helper/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ tree-sitter-typescript = { git = "https://github.com/tree-sitter/tree-sitter-typ
tree-sitter-php = { git = "https://github.com/tree-sitter/tree-sitter-php", rev = "d43130f" }
tree-sitter-r = { git = "https://github.com/r-lib/tree-sitter-r", rev = "c55f8b4" }
tree-sitter-scala = { git = "https://github.com/tree-sitter/tree-sitter-scala", rev = "f14629b" }
tree-sitter-svelte = { git = "https://github.com/Himujjal/tree-sitter-svelte", rev = "697bb51" }
1 change: 1 addition & 0 deletions helper/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub fn load_doc_config_str<'a>(parser_name: &'a str, doc_name: &'a str) -> &'a s

"php_phpdoc" => include_str!("php/docs/phpdoc.yaml"),
"typescript_jsdoc" => include_str!("typescript/docs/jsdoc.yaml"),
"svelte_jsdoc" => include_str!("typescript/docs/jsdoc.yaml"),
"lua_ldoc" => include_str!("lua/docs/ldoc.yaml"),
"java_javadoc" => include_str!("java/docs/javadoc.yaml"),
"ruby_YARD" => include_str!("ruby/docs/YARD.yaml"),
Expand Down
2 changes: 2 additions & 0 deletions helper/src/docblock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::rust::parser::RustParser;
use crate::typescript::parser::TypescriptParser;
use crate::r::parser::RParser;
use crate::scala::parser::ScalaParser;
use crate::svelte::parser::SvelteParser;


fn replace_indent_placeholders(docblock: &str, use_tabs: bool, indent: usize) -> String {
Expand Down Expand Up @@ -141,6 +142,7 @@ pub fn generate(
"typescript" => Box::new(TypescriptParser::new(code, line, &node_types, options)) as Box<dyn BaseParser>,
"r" => Box::new(RParser::new(code, line, &node_types)) as Box<dyn BaseParser>,
"scala" => Box::new(ScalaParser::new(code, line, &node_types)) as Box<dyn BaseParser>,
"svelte" => Box::new(SvelteParser::new(code, line, &node_types, options)) as Box<dyn BaseParser>,
_ => panic!("Unsupported parser: {}", &parser_name),
};

Expand Down
1 change: 1 addition & 0 deletions helper/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ pub mod cpp;
pub mod typescript;
pub mod r;
pub mod scala;
pub mod svelte;
1 change: 1 addition & 0 deletions helper/src/svelte/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod parser;
63 changes: 63 additions & 0 deletions helper/src/svelte/parser.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use std::collections::HashMap;

use tree_sitter::{Parser, Node};
use serde_json::{Map, Value};

use crate::traverse;
use crate::base_parser::BaseParser;
use crate::typescript::parser::TypescriptParser;

pub struct SvelteParser<'a> {
code: &'a str,
tree: tree_sitter::Tree,
line: &'a usize,
node_types: &'a [&'a str],
options: &'a HashMap<&'a str, bool>,
}

impl<'a> BaseParser for SvelteParser<'a> {
fn parse(&self) -> Option<Result<Map<String, Value>, String>> {
self.parse_node(&self.tree.root_node())
}

fn get_code_bytes(&self) -> &[u8] {
&self.code.as_bytes()
}
}

impl<'a> SvelteParser<'a> {
pub fn new(code: &'a str, line: &'a usize, node_types: &'a [&'a str], options: &'a HashMap<&'a str, bool>) -> Self {
let mut parser = Parser::new();
parser.set_language(tree_sitter_svelte::language()).unwrap();

let tree = parser.parse(code, None).unwrap();

Self { code, tree, line, options, node_types }
}

fn parse_node(&self, node: &Node) -> Option<Result<Map<String, Value>, String>> {
for child_node in traverse::PreOrder::new(node.walk()) {
if child_node.kind() == "script_element" {
return self.parse_script_element(&child_node);
}
}

None
}

fn parse_script_element(&self, node: &Node) -> Option<Result<Map<String, Value>, String>> {
let raw_text = node
.children(&mut node.walk())
.filter(|node| node.kind() == "raw_text")
.next()
.and_then(|node| Some(self.get_node_text(&node)))
.unwrap();

// The new line must be based on the script tag starting position.
let line = self.line - (node.start_position().row + 1);

// Parse the inner content of the script tag with the TS parser.
let ts_parser = TypescriptParser::new(&raw_text, &line, self.node_types, self.options);
ts_parser.parse()
}
}
55 changes: 55 additions & 0 deletions test/filetypes/svelte/hello-world.vader
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
Given svelte (hello world example with template and script tag):
<template>
<div>
<h1>Hello {{ name }}!</h1>
</div>
</template>

<script>
export default {
data() {
return {
name: 'world'
}
},
methods: {
foo(test) {}
}
}
</script>

Do (trigger doge):
:9\<CR>
\<C-d>
:20\<CR>
\<C-d>

Expect typescript (generated comment with generated comment inside <script>):
<template>
<div>
<h1>Hello {{ name }}!</h1>
</div>
</template>

<script>
export default {
/**
* [TODO:description]
*
* @returns [TODO:description]
*/
data() {
return {
name: 'world'
}
},
methods: {
/**
* [TODO:description]
*
* @param {[TODO:type]} test - [TODO:description]
*/
foo(test) {}
}
}
</script>
138 changes: 138 additions & 0 deletions test/filetypes/svelte/table-component.vader
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
Given svelte (table layout component with script, style and template elements):
<template>
<div class="table-container">
<table>
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
</tr>
</thead>
<tbody>
<tr v-for="item in items" :key="item.id">
<td>{{ item.field1 }}</td>
<td>{{ item.field2 }}</td>
<td>{{ item.field3 }}</td>
</tr>
</tbody>
</table>
</div>
</template>

<script>
export default {
data() {
return {
items: [
{ id: 1, field1: 'Data 1', field2: 'Data 2', field3: 'Data 3' },
{ id: 2, field1: 'Data 4', field2: 'Data 5', field3: 'Data 6' },
{ id: 3, field1: 'Data 7', field2: 'Data 8', field3: 'Data 9' }
]
};
}
};
</script>

<style scoped>
.table-container {
font-family: Arial, sans-serif;
margin: 20px;
}

table {
border-collapse: collapse;
width: 100%;
}

th, td {
border: 1px solid #ddd;
padding: 8px;
}

th {
background-color: #f2f2f2;
}

tr:nth-child(even) {
background-color: #f9f9f9;
}

tr:hover {
background-color: #ddd;
}
</style>

Do (trigger doge):
:24\<CR>
\<C-d>

Expect typescript (generated comment with generated comment inside <script>):
<template>
<div class="table-container">
<table>
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
</tr>
</thead>
<tbody>
<tr v-for="item in items" :key="item.id">
<td>{{ item.field1 }}</td>
<td>{{ item.field2 }}</td>
<td>{{ item.field3 }}</td>
</tr>
</tbody>
</table>
</div>
</template>

<script>
export default {
/**
* [TODO:description]
*
* @returns [TODO:description]
*/
data() {
return {
items: [
{ id: 1, field1: 'Data 1', field2: 'Data 2', field3: 'Data 3' },
{ id: 2, field1: 'Data 4', field2: 'Data 5', field3: 'Data 6' },
{ id: 3, field1: 'Data 7', field2: 'Data 8', field3: 'Data 9' }
]
};
}
};
</script>

<style scoped>
.table-container {
font-family: Arial, sans-serif;
margin: 20px;
}

table {
border-collapse: collapse;
width: 100%;
}

th, td {
border: 1px solid #ddd;
padding: 8px;
}

th {
background-color: #f2f2f2;
}

tr:nth-child(even) {
background-color: #f9f9f9;
}

tr:hover {
background-color: #ddd;
}
</style>
2 changes: 1 addition & 1 deletion test/vimrc
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ set autoindent
set smartindent
set smarttab

augroup styles
augroup vim_doge_tests
autocmd!

" Force 2 spaces for Python to prevent other filetypes inherit these settings.
Expand Down

0 comments on commit 395e4ef

Please sign in to comment.