{"id":34955710,"url":"https://github.com/wickedev/wyreframe","last_synced_at":"2026-03-17T20:16:21.304Z","repository":{"id":330623534,"uuid":"1121058571","full_name":"wickedev/wyreframe","owner":"wickedev","description":"A library that converts ASCII wireframes into working HTML/UI with scene management","archived":false,"fork":false,"pushed_at":"2025-12-27T15:08:47.000Z","size":549,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-28T09:41:19.618Z","etag":null,"topics":["ascii","html","prototyping","rescript","scene-management","ui","wireframe"],"latest_commit_sha":null,"homepage":"https://wyreframe.studio","language":"ReScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wickedev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-22T11:21:22.000Z","updated_at":"2025-12-27T15:08:50.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/wickedev/wyreframe","commit_stats":null,"previous_names":["wickedev/wyreframe"],"tags_count":27,"template":false,"template_full_name":null,"purl":"pkg:github/wickedev/wyreframe","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wickedev%2Fwyreframe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wickedev%2Fwyreframe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wickedev%2Fwyreframe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wickedev%2Fwyreframe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wickedev","download_url":"https://codeload.github.com/wickedev/wyreframe/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wickedev%2Fwyreframe/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30630409,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-17T17:32:55.572Z","status":"ssl_error","status_checked_at":"2026-03-17T17:32:38.732Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ascii","html","prototyping","rescript","scene-management","ui","wireframe"],"created_at":"2025-12-26T22:01:11.015Z","updated_at":"2026-03-17T20:16:21.297Z","avatar_url":"https://github.com/wickedev.png","language":"ReScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Wyreframe\n\n\u003e A library that converts ASCII wireframes into working HTML/UI with scene management\n\n[![npm version](https://img.shields.io/npm/v/wyreframe.svg)](https://www.npmjs.com/package/wyreframe)\n[![npm downloads](https://img.shields.io/npm/dm/wyreframe.svg)](https://www.npmjs.com/package/wyreframe)\n[![codecov](https://codecov.io/gh/wickedev/wyreframe/branch/main/graph/badge.svg)](https://codecov.io/gh/wickedev/wyreframe)\n[![License: GPL-3.0](https://img.shields.io/badge/License-GPL--3.0-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)\n[![ReScript](https://img.shields.io/badge/ReScript-12-e6484f.svg)](https://rescript-lang.org/)\n[![Node.js](https://img.shields.io/badge/Node.js-20+-green.svg)](https://nodejs.org/)\n\n```\n+---------------------------+\n|      'WYREFRAME'          |     Draw in ASCII\n|  +---------------------+  |         ↓\n|  | #email              |  |     Convert to HTML!\n|  +---------------------+  |\n|       [ Login ]           |\n+---------------------------+\n```\n\n## Features\n\n- **ASCII to HTML**: Convert simple ASCII art into interactive UI elements\n- **Scene Management**: Multi-screen prototypes with transitions (fade, slide, zoom)\n- **Interaction DSL**: Define button clicks, navigation, and form validation\n- **Device Preview**: Responsive previews for mobile, tablet, and desktop\n- **Auto-Fix**: Automatically correct common wireframe formatting issues\n- **TypeScript/ReScript**: Full type safety with both language support\n\n## Installation\n\n```bash\nnpm install wyreframe\n```\n\n## Quick Start\n\n```javascript\nimport { createUI } from 'wyreframe';\n\nconst ui = `\n@scene: login\n\n+---------------------------+\n|       'WYREFRAME'         |\n|  +---------------------+  |\n|  | #email              |  |\n|  +---------------------+  |\n|       [ Login ]           |\n+---------------------------+\n\n#email:\n  placeholder: \"Enter your email\"\n\n[Login]:\n  @click -\u003e goto(dashboard, slide-left)\n`;\n\nconst result = createUI(ui);\n\nif (result.success) {\n  document.getElementById('app').appendChild(result.root);\n  result.sceneManager.goto('login');\n}\n```\n\n## Syntax Reference\n\n### UI Elements\n\n| Syntax | Description | HTML Output |\n|--------|-------------|-------------|\n| `+---+` | Box/Container | `\u003cdiv\u003e` |\n| `[ Text ]` | Button | `\u003cbutton\u003e` |\n| `#id` | Input field | `\u003cinput\u003e` |\n| `\"text\"` | Link | `\u003ca\u003e` |\n| `'text'` | Emphasis text | Title, Heading |\n| `[x]` / `[ ]` | Checkbox | `\u003cinput type=\"checkbox\"\u003e` |\n| `---` | Divider | `\u003chr\u003e` |\n\n### Scene Directives\n\n```yaml\n@scene: sceneId        # Scene identifier (required)\n@title: Page Title     # Optional page title\n@device: mobile        # Device type for sizing\n@transition: fade      # Default transition effect\n```\n\n### Device Types\n\n| Device | Dimensions | Description |\n|--------|------------|-------------|\n| `desktop` | 1440x900 | Desktop monitor |\n| `laptop` | 1280x800 | Laptop screen |\n| `tablet` | 768x1024 | Tablet portrait |\n| `tablet-landscape` | 1024x768 | Tablet landscape |\n| `mobile` | 375x812 | iPhone X ratio |\n| `mobile-landscape` | 812x375 | Mobile landscape |\n\n### Interactions\n\n```yaml\n#email:\n  placeholder: \"Email\"\n\n[Login]:\n  variant: primary\n  @click -\u003e goto(dashboard, slide-left)\n\n\"Forgot Password\":\n  @click -\u003e goto(reset)\n```\n\n**Actions:**\n\n| Action | Description | Example |\n|--------|-------------|---------|\n| `goto(scene, transition?)` | Navigate to scene | `@click -\u003e goto(home, fade)` |\n| `back()` | Navigate back | `@click -\u003e back()` |\n| `forward()` | Navigate forward | `@click -\u003e forward()` |\n| `validate(fields)` | Validate inputs | `@submit -\u003e validate(email, password)` |\n| `call(fn, args)` | Custom function | `@click -\u003e call(submit, form)` |\n\n**Transitions:** `fade`, `slide-left`, `slide-right`, `zoom`\n\n**Variants:** `primary`, `secondary`, `ghost`\n\n## API\n\n### JavaScript/TypeScript\n\n```javascript\nimport {\n  parse,\n  parseOrThrow,\n  render,\n  createUI,\n  createUIOrThrow,\n  fix,\n  fixOnly\n} from 'wyreframe';\n\n// Parse only - returns { success, ast, warnings } or { success: false, errors }\nconst parseResult = parse(text);\n\n// Parse and throw on error\nconst ast = parseOrThrow(text);\n\n// Render AST to DOM (pass ast, not parseResult!)\nif (parseResult.success) {\n  const { root, sceneManager } = render(parseResult.ast, options);\n}\n\n// Parse + Render combined (recommended)\nconst result = createUI(text, options);\n\n// Parse + Render, throw on error\nconst { root, sceneManager } = createUIOrThrow(text, options);\n\n// Auto-fix wireframe formatting issues\nconst fixResult = fix(text);\nif (fixResult.success) {\n  console.log('Fixed:', fixResult.fixed.length, 'issues');\n  const cleanText = fixResult.text;\n}\n\n// Fix and return text only\nconst fixedText = fixOnly(text);\n```\n\n### Render Options\n\n```typescript\nconst options = {\n  // Additional CSS class for container\n  containerClass: 'my-app',\n\n  // Inject default styles (default: true)\n  injectStyles: true,\n\n  // Override device type for all scenes\n  device: 'mobile',\n\n  // Scene change callback\n  onSceneChange: (fromScene, toScene) =\u003e {\n    console.log(`Navigated from ${fromScene} to ${toScene}`);\n  },\n\n  // Dead-end click callback (buttons/links without navigation)\n  onDeadEndClick: (info) =\u003e {\n    console.log(`Clicked: ${info.elementText} in scene ${info.sceneId}`);\n    // Show modal, custom logic, etc.\n  }\n};\n\nconst result = createUI(text, options);\n```\n\n### SceneManager\n\n```javascript\nconst { sceneManager } = result;\n\nsceneManager.goto('dashboard');        // Navigate to scene\nsceneManager.goto('home', 'fade');     // Navigate with transition\nsceneManager.back();                   // Go back in history\nsceneManager.forward();                // Go forward in history\nsceneManager.getCurrentScene();        // Get current scene ID\nsceneManager.getSceneIds();            // Get all scene IDs\n```\n\n### ReScript\n\n```rescript\n// Parse + Render\nswitch Renderer.createUI(ui, None) {\n| Ok({root, sceneManager, _}) =\u003e\n    sceneManager.goto(\"login\")\n| Error(errors) =\u003e Console.error(errors)\n}\n\n// With options\nlet options = {\n  device: Some(#mobile),\n  onSceneChange: Some((from, to) =\u003e Console.log2(from, to)),\n  onDeadEndClick: None,\n  containerClass: None,\n  injectStyles: None,\n}\nswitch Renderer.createUI(ui, Some(options)) {\n| Ok({root, sceneManager, _}) =\u003e ...\n| Error(errors) =\u003e ...\n}\n```\n\n## Auto-Fix\n\nWyreframe can automatically fix common formatting issues:\n\n```javascript\nimport { fix, fixOnly } from 'wyreframe';\n\nconst messyWireframe = `\n+----------+\n| Button  |    \u003c- Misaligned pipe\n+---------+    \u003c- Width mismatch\n`;\n\nconst result = fix(messyWireframe);\nif (result.success) {\n  console.log('Fixed issues:', result.fixed);\n  console.log('Remaining issues:', result.remaining);\n  console.log('Clean wireframe:', result.text);\n}\n\n// Or just get the fixed text\nconst cleanText = fixOnly(messyWireframe);\n```\n\n**Fixable Issues:**\n- Misaligned pipes (|)\n- Mismatched border widths\n- Tabs instead of spaces\n- Unclosed brackets\n\n## Multi-Scene Example\n\n```javascript\nconst app = `\n@scene: login\n@device: mobile\n\n+---------------------------+\n|         'Login'           |\n|  +---------------------+  |\n|  | #email              |  |\n|  +---------------------+  |\n|  +---------------------+  |\n|  | #password           |  |\n|  +---------------------+  |\n|       [ Sign In ]         |\n|                           |\n|    \"Create Account\"       |\n+---------------------------+\n\n---\n\n@scene: signup\n@device: mobile\n\n+---------------------------+\n|       'Sign Up'           |\n|  +---------------------+  |\n|  | #name               |  |\n|  +---------------------+  |\n|  +---------------------+  |\n|  | #email              |  |\n|  +---------------------+  |\n|       [ Register ]        |\n|                           |\n|    \"Back to Login\"        |\n+---------------------------+\n\n#email:\n  placeholder: \"Email\"\n#password:\n  placeholder: \"Password\"\n#name:\n  placeholder: \"Full Name\"\n\n[Sign In]:\n  variant: primary\n  @click -\u003e goto(signup, slide-left)\n\n\"Create Account\":\n  @click -\u003e goto(signup, slide-left)\n\n[Register]:\n  variant: primary\n  @click -\u003e goto(login, slide-right)\n\n\"Back to Login\":\n  @click -\u003e goto(login, slide-right)\n`;\n\nconst result = createUI(app, {\n  onSceneChange: (from, to) =\u003e {\n    console.log(`Scene: ${from} -\u003e ${to}`);\n  }\n});\n\nif (result.success) {\n  document.getElementById('app').appendChild(result.root);\n  result.sceneManager.goto('login');\n}\n```\n\n## Documentation\n\n- [API Reference](docs/api.md)\n- [Type Definitions](docs/types.md)\n- [Examples](docs/examples.md)\n- [Developer Guide](docs/developer-guide.md)\n- [Testing Guide](docs/testing.md)\n- [Live Demo](https://wyreframe.studio/)\n\n## Development\n\n```bash\nnpm install\nnpm run res:build    # ReScript build\nnpm run ts:build     # TypeScript build\nnpm run build        # Full build\nnpm run dev          # Dev server (http://localhost:3000/examples)\nnpm test             # Run tests\nnpm run test:watch   # Test watch mode\nnpm run test:coverage # Generate coverage report\n```\n\n## Architecture\n\nWyreframe uses a 3-stage parsing pipeline:\n\n1. **Grid Scanner**: Converts ASCII text to 2D character grid\n2. **Shape Detector**: Identifies boxes, nesting, and hierarchy\n3. **Semantic Parser**: Recognizes UI elements via pluggable parsers\n\nThe renderer generates pure DOM elements with CSS-based scene visibility and transitions.\n\n## License\n\nGPL-3.0 License - see [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwickedev%2Fwyreframe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwickedev%2Fwyreframe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwickedev%2Fwyreframe/lists"}