@zenithbuild/language-server 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,77 @@
1
+ <!--
2
+ Test Fixture: Content Plugin
3
+
4
+ This file tests Zenith features WITH content plugin imported.
5
+ The LSP should provide content-aware completions and soft warnings.
6
+ -->
7
+ <script>
8
+ import { zenEffect, zenOnMount } from 'zenith'
9
+ import { zenCollection, getCollection, getEntry } from 'zenith:content'
10
+
11
+ state posts = []
12
+ state currentPost = null
13
+
14
+ // Define a content collection
15
+ const blogCollection = zenCollection({
16
+ name: 'blog',
17
+ schema: {
18
+ title: 'string',
19
+ date: 'date',
20
+ author: 'string',
21
+ tags: 'array'
22
+ }
23
+ })
24
+
25
+ zenOnMount(async () => {
26
+ // Get all posts from the collection
27
+ posts = await getCollection('blog')
28
+ })
29
+
30
+ async function loadPost(slug) {
31
+ currentPost = await getEntry('blog', slug)
32
+ }
33
+ </script>
34
+
35
+ <div class="blog-list">
36
+ <h1>Blog Posts</h1>
37
+
38
+ <!-- List all posts -->
39
+ <ul zen:if="posts.length > 0">
40
+ <li zen:for="post in posts">
41
+ <h2>{post.data.title}</h2>
42
+ <p>By {post.data.author} on {post.data.date}</p>
43
+ <button onclick={() => loadPost(post.slug)}>Read More</button>
44
+ </li>
45
+ </ul>
46
+
47
+ <p zen:if="posts.length === 0">Loading posts...</p>
48
+
49
+ <!-- Current post display -->
50
+ <article zen:if="currentPost">
51
+ <h1>{currentPost.data.title}</h1>
52
+ <div class="meta">
53
+ <span>By {currentPost.data.author}</span>
54
+ <span>{currentPost.data.date}</span>
55
+ </div>
56
+ <div class="content">
57
+ {currentPost.content}
58
+ </div>
59
+ </article>
60
+ </div>
61
+
62
+ <style>
63
+ .blog-list {
64
+ max-width: 800px;
65
+ margin: 0 auto;
66
+ padding: 2rem;
67
+ }
68
+ article {
69
+ margin-top: 2rem;
70
+ padding-top: 2rem;
71
+ border-top: 1px solid #eee;
72
+ }
73
+ .meta {
74
+ color: #666;
75
+ margin-bottom: 1rem;
76
+ }
77
+ </style>
@@ -0,0 +1,59 @@
1
+ <!--
2
+ Test Fixture: Core Only
3
+
4
+ This file tests core Zenith features WITHOUT router or plugins.
5
+ The LSP should work correctly with just core functionality.
6
+ -->
7
+ <script>
8
+ import { zenEffect, zenOnMount } from 'zenith'
9
+
10
+ state count = 0
11
+ state message = "Hello, Zenith!"
12
+
13
+ function increment() {
14
+ count++
15
+ }
16
+
17
+ zenOnMount(() => {
18
+ console.log('Component mounted')
19
+ })
20
+
21
+ zenEffect(() => {
22
+ console.log('Count changed:', count)
23
+ })
24
+ </script>
25
+
26
+ <div class="container">
27
+ <h1>{message}</h1>
28
+
29
+ <!-- zen:if directive -->
30
+ <p zen:if="count > 0">Count is positive: {count}</p>
31
+
32
+ <!-- zen:for directive -->
33
+ <ul>
34
+ <li zen:for="item in ['a', 'b', 'c']">{item}</li>
35
+ </ul>
36
+
37
+ <!-- zen:show directive -->
38
+ <span zen:show="count !== 0">Not zero!</span>
39
+
40
+ <!-- Event handlers -->
41
+ <button onclick={increment}>Increment</button>
42
+ <button @click={increment}>Also Increment</button>
43
+
44
+ <!-- Reactive bindings -->
45
+ <input :value="message" />
46
+ <div :class="count > 0 ? 'positive' : 'zero'">{count}</div>
47
+ </div>
48
+
49
+ <style>
50
+ .container {
51
+ padding: 1rem;
52
+ }
53
+ .positive {
54
+ color: green;
55
+ }
56
+ .zero {
57
+ color: gray;
58
+ }
59
+ </style>
@@ -0,0 +1,115 @@
1
+ <!--
2
+ Test Fixture: No Plugins
3
+
4
+ This file tests behavior when NO external imports are used.
5
+ The LSP should work with just vanilla Zenith features.
6
+
7
+ Validation rules:
8
+ - Removing router should not crash the IDE
9
+ - Missing plugin imports should show soft warnings
10
+ - Invalid syntax should be surfaced immediately
11
+ - IDE should never suggest unavailable APIs
12
+ -->
13
+ <script>
14
+ // No imports - just vanilla state and lifecycle
15
+ state items = ['Apple', 'Banana', 'Cherry']
16
+ state selectedIndex = 0
17
+ state filter = ''
18
+
19
+ function selectItem(index) {
20
+ selectedIndex = index
21
+ }
22
+
23
+ function addItem() {
24
+ items = [...items, 'New Item']
25
+ }
26
+
27
+ function removeItem(index) {
28
+ items = items.filter((_, i) => i !== index)
29
+ }
30
+
31
+ // Computed-like pattern
32
+ function getFilteredItems() {
33
+ if (!filter) return items
34
+ return items.filter(item =>
35
+ item.toLowerCase().includes(filter.toLowerCase())
36
+ )
37
+ }
38
+ </script>
39
+
40
+ <div class="app">
41
+ <header>
42
+ <h1>Simple List App</h1>
43
+ <p>Selected: {items[selectedIndex] || 'None'}</p>
44
+ </header>
45
+
46
+ <div class="controls">
47
+ <input
48
+ type="text"
49
+ placeholder="Filter items..."
50
+ :value="filter"
51
+ oninput={(e) => filter = e.target.value}
52
+ />
53
+ <button onclick={addItem}>Add Item</button>
54
+ </div>
55
+
56
+ <ul class="item-list">
57
+ <li
58
+ zen:for="item, index in getFilteredItems()"
59
+ :class="index === selectedIndex ? 'selected' : ''"
60
+ >
61
+ <span onclick={() => selectItem(index)}>{item}</span>
62
+ <button onclick={() => removeItem(index)}>Remove</button>
63
+ </li>
64
+ </ul>
65
+
66
+ <p zen:if="getFilteredItems().length === 0">
67
+ No items match the filter.
68
+ </p>
69
+
70
+ <footer>
71
+ <p>Total items: {items.length}</p>
72
+ <p zen:show="filter">Filtered: {getFilteredItems().length}</p>
73
+ </footer>
74
+ </div>
75
+
76
+ <style>
77
+ .app {
78
+ max-width: 600px;
79
+ margin: 0 auto;
80
+ padding: 1rem;
81
+ }
82
+ header {
83
+ margin-bottom: 1rem;
84
+ }
85
+ .controls {
86
+ display: flex;
87
+ gap: 0.5rem;
88
+ margin-bottom: 1rem;
89
+ }
90
+ .controls input {
91
+ flex: 1;
92
+ padding: 0.5rem;
93
+ }
94
+ .item-list {
95
+ list-style: none;
96
+ padding: 0;
97
+ }
98
+ .item-list li {
99
+ display: flex;
100
+ justify-content: space-between;
101
+ padding: 0.5rem;
102
+ border-bottom: 1px solid #eee;
103
+ cursor: pointer;
104
+ }
105
+ .item-list li.selected {
106
+ background: #e0f0ff;
107
+ }
108
+ .item-list li:hover {
109
+ background: #f5f5f5;
110
+ }
111
+ footer {
112
+ margin-top: 1rem;
113
+ color: #666;
114
+ }
115
+ </style>
@@ -0,0 +1,76 @@
1
+ <!--
2
+ Test Fixture: Router Enabled
3
+
4
+ This file tests Zenith features WITH router imported.
5
+ The LSP should provide router-aware completions and hovers.
6
+ -->
7
+ <script>
8
+ import { zenEffect, zenOnMount } from 'zenith'
9
+ import { ZenLink, useRoute, useRouter, navigate, prefetch } from 'zenith/router'
10
+
11
+ state activeSection = 'home'
12
+
13
+ // Router hooks - should have hover info
14
+ const route = useRoute()
15
+ const router = useRouter()
16
+
17
+ zenOnMount(() => {
18
+ // Prefetch common routes
19
+ prefetch('/about')
20
+ prefetch('/blog')
21
+ })
22
+
23
+ zenEffect(() => {
24
+ // React to route changes
25
+ activeSection = route.path.split('/')[1] || 'home'
26
+ })
27
+
28
+ function goToAbout() {
29
+ navigate('/about')
30
+ }
31
+
32
+ function goBack() {
33
+ router.back()
34
+ }
35
+ </script>
36
+
37
+ <nav>
38
+ <!-- ZenLink components - should have special highlighting and props -->
39
+ <ZenLink to="/">Home</ZenLink>
40
+ <ZenLink to="/about" preload>About</ZenLink>
41
+ <ZenLink to="/blog" preload replace>Blog</ZenLink>
42
+
43
+ <!-- Dynamic route params -->
44
+ <ZenLink to="/blog/{route.params.slug}">Current Post</ZenLink>
45
+ </nav>
46
+
47
+ <main>
48
+ <h1>Current path: {route.path}</h1>
49
+
50
+ <!-- Route params and query -->
51
+ <p zen:if="route.params.id">Viewing item: {route.params.id}</p>
52
+ <p zen:if="route.query.search">Searching: {route.query.search}</p>
53
+
54
+ <div class="actions">
55
+ <button onclick={goToAbout}>Go to About</button>
56
+ <button onclick={goBack}>Go Back</button>
57
+ </div>
58
+
59
+ <!-- Slot for page content -->
60
+ <slot />
61
+ </main>
62
+
63
+ <style>
64
+ nav {
65
+ display: flex;
66
+ gap: 1rem;
67
+ padding: 1rem;
68
+ background: #f0f0f0;
69
+ }
70
+ main {
71
+ padding: 2rem;
72
+ }
73
+ .actions {
74
+ margin-top: 1rem;
75
+ }
76
+ </style>
package/tsconfig.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "commonjs",
5
+ "lib": [
6
+ "ES2022"
7
+ ],
8
+ "outDir": "./dist",
9
+ "rootDir": "./src",
10
+ "strict": true,
11
+ "esModuleInterop": true,
12
+ "skipLibCheck": true,
13
+ "forceConsistentCasingInFileNames": true,
14
+ "declaration": true,
15
+ "resolveJsonModule": true,
16
+ "moduleResolution": "node"
17
+ },
18
+ "include": [
19
+ "src/**/*"
20
+ ],
21
+ "exclude": [
22
+ "node_modules",
23
+ "dist"
24
+ ]
25
+ }