Skip to content
/ ovsjs Public

OVS - a pure JavaScript declarative UI, a Vue DSL that lets you write Vue with a more concise, elegant, and flexible syntax, inspired by Kotlin-HTML, SwiftUI, and SolidJS.

License

Notifications You must be signed in to change notification settings

alamhubb/ovsjs

Repository files navigation

OVS - Object View Script

OVS - A pure JavaScript declarative UI, a Vue DSL that lets you write Vue with a more concise, elegant, and flexible syntax, inspired by Kotlin-HTML, SwiftUI, and SolidJS.

Documentation VSCode Extension License

English | 中文

Quick StartBasic SyntaxAdvanced UsageDesign PhilosophyCompilation Principles


Introduction

OVS is a declarative UI syntax extension that lets you write Vue components in a more concise way:

// OVS syntax
div({ class: 'container' }) {
  h1 { 'Hello OVS!' }
  button({ onClick: handleClick }) { 'Click Me' }
}

Features:

  • Pure JavaScript Superset - All JS syntax works
  • Zero Template Directives - No v-if, v-for, just native if/for
  • No JSX Required - Native brace syntax, no className, no {} wrapping
  • Full IDE Support - Code completion, type checking, go to definition
  • Vue 3 Runtime - Compiles to efficient Vue render functions

Why OVS?

OVS solves the flexibility problem of Vue templates while being more elegant than JSX.

Vue Template vs JSX vs OVS

Conditional Rendering:

// ❌ Vue Template - Custom directives, limited flexibility
<template>
  <div v-if="isLoggedIn">Welcome, {{ username }}</div>
  <div v-else>Please login</div>
</template>

// ❌ JSX - Ternary expressions, hard to read when nested
{isLoggedIn ? <div>Welcome, {username}</div> : <div>Please login</div>}

// ✅ OVS - Native JavaScript, clean and intuitive
if (isLoggedIn) {
  div { `Welcome, ${username}` }
} else {
  div { 'Please login' }
}

List Rendering:

// ❌ Vue Template - v-for directive, special :key syntax
<template>
  <ul>
    <li v-for="item in items" :key="item.id">{{ item.name }}</li>
  </ul>
</template>

// ❌ JSX - .map() callback, requires return and key prop
<ul>
  {items.map(item => <li key={item.id}>{item.name}</li>)}
</ul>

// ✅ OVS - Native for...of, straightforward
ul {
  for (const item of items) {
    li { item.name }
  }
}

Complex Logic:

// ❌ Vue Template - Need computed properties or methods for complex logic
// ❌ JSX - Inline logic becomes messy with && and ternary chains

// ✅ OVS - Just write JavaScript!
div {
  const total = items.reduce((sum, item) => sum + item.price, 0)

  if (total > 100) {
    span({ class: 'discount' }) { 'Free shipping!' }
  }

  for (const item of items) {
    if (item.inStock) {
      ProductCard({ product: item })
    }
  }
}

Key Advantages

Feature Vue Template JSX OVS
Control Flow v-if, v-for directives &&, ? :, .map() Native if, for
Class Attribute class className class
Expression Syntax {{ }} { } Direct reference
Learning Curve Template syntax JSX rules Just JavaScript
Flexibility Limited High High
Readability Good for simple Complex nesting Clean & intuitive

Quick Start

1. Create Project

npm create ovs@latest my-app
cd my-app
npm install
npm run dev

2. Install VSCode Extension

Install Ovs Language from VSCode Extensions Marketplace.

3. Start Writing

Create a .ovs file:

// src/components/Hello.ovs
import { ref } from 'vue'

const count = ref(0)

div({ class: 'hello' }) {
  h1 { 'Hello OVS!' }
  p { `Count: ${count.value}` }
  button({ onClick: () => count.value++ }) { '+1' }
}

Basic Syntax

Element Declaration

Use tagName { content } to declare elements:

div { 'Hello World' }

// Nested elements
div {
  h1 { 'Title' }
  p { 'Content' }
}

Passing Props

Use tagName(propsObject) { content } to pass props:

div({ class: 'container', id: 'app' }) {
  a({ href: 'https://example.com', target: '_blank' }) {
    'Click here'
  }
}

// Event handling
button({ onClick: () => console.log('clicked') }) {
  'Click Me'
}

Text and Expressions

Write strings or JavaScript expressions directly:

div {
  'Static text'           // Static text
  `Dynamic: ${value}`     // Template string
  someVariable            // Variable
  computedValue()         // Function call
}

Conditional Rendering

Use standard JavaScript conditional statements:

div {
  if (isLoggedIn) {
    span { `Welcome, ${username}` }
  } else {
    button { 'Login' }
  }
}

List Rendering

Use for...of loops:

ul {
  for (const item of items) {
    li { item.name }
  }
}

Component Definition

Use the view soft keyword to define reusable components:

// Define component
view Card(state) {
  div({ class: 'card' }) {
    h2 { state.props.title }
    p { state.props.content }
    state.children  // Render children
  }
}

// Use component
Card({ title: 'Hello', content: 'World' }) {
  span { 'Extra content' }
}

Note: view is a soft keyword (contextual keyword), only has special meaning at component declaration position. You can still use view as a variable name elsewhere: const view = someValue


Advanced Usage

Non-Rendering Block #{}

Code inside #{} won't be rendered to DOM, used for pure logic:

div {
  #{
    // Pure JS logic here, won't render
    const data = processData(rawData)
    console.log('Processing...')
  }

  // This will render
  span { data.result }
}

Reactive Data

Works with Vue's ref and reactive:

import { ref, reactive } from 'vue'

const count = ref(0)
const user = reactive({ name: 'Alice', age: 25 })

div {
  p { `Count: ${count.value}` }
  p { `Name: ${user.name}` }
  button({ onClick: () => count.value++ }) { 'Add' }
}

Complete Example

// HelloWorld.ovs
import { ref } from 'vue'

const msg = "You did it!"
const count = ref(0)

div({ class: 'greetings', onClick: () => count.value = 0 }) {
  h1({ class: 'green' }) { msg }

  #{
    // Pure logic code, won't render
    console.log('Component rendered')
  }

  h2 { `Clicked ${count.value} times` }

  h3 {
    "Built with "
    a({ href: 'https://vuejs.org/', target: '_blank' }) { 'Vue 3' }
    ' + '
    a({ href: 'https://github.com/aspect-apps/ovsjs', target: '_blank' }) { 'OVS' }
  }

  button({ onClick: () => count.value++ }) { 'Click Me' }
}

Design Philosophy & Principles

Design Philosophy

1. JavaScript Superset, Minimal Intrusion

OVS only adds three syntax extensions:

  • tag {} / tag() {} - Element declaration
  • view Name() {} - Component declaration (view is a soft keyword, can be used as variable name)
  • #{} - Non-rendering block

Everything else is standard JavaScript, minimal learning curve.

2. Declarative UI, No JSX Required

No need to learn JSX syntax, native braces {} are more natural for JavaScript:

// JSX approach
<div className="container">
  <h1>{title}</h1>
</div>

// OVS approach
div({ class: 'container' }) {
  h1 { title }
}

3. Full Type Support

OVS compiler generates precise Source Maps, enabling IDE to:

  • Accurately locate original .ovs file positions
  • Provide complete TypeScript type checking
  • Support go-to-definition, rename, and other refactoring features

Core Tech Stack

Component Description
Subhuti Parser generator framework, define grammar rules with decorators
Slime JavaScript/TypeScript fault-tolerant parser
Volar Language Server framework, provides IDE support
Vue 3 Runtime framework

Project Structure

test-volar/
├── ovs/                    # OVS compiler + runtime
│   ├── ovs-compiler/       # Compiler (Parser + AST transform)
│   └── ovs-runtime/        # Runtime ($OvsHtmlTag + defineOvsComponent)
├── ovs-language/           # VSCode extension
├── create-ovs/             # Project scaffolding
├── vite-plugin-ovs/        # Vite plugin
├── slime/                  # JS/TS parser
└── subhuti/                # Parser framework

📄 License

MIT License


🤝 Contributing

Issues and Pull Requests are welcome!


🔗 Links

  • Documentation: deepwiki.com/alamhubb/ovsjs
  • Topics: vue-kotlin vue-dsl declarative-vue declarative-ui-syntax-in-vue vue-swiftui vue-flutter vue-solidjs vue-dsl-in-pure-javascript declarative-dsl-vue

OVS - Declarative UI for the Web, Concise & Elegant

About

OVS - a pure JavaScript declarative UI, a Vue DSL that lets you write Vue with a more concise, elegant, and flexible syntax, inspired by Kotlin-HTML, SwiftUI, and SolidJS.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published