tangled
alpha
login
or
join now
danabra.mov
/
typelex
56
fork
atom
An experimental TypeSpec syntax for Lexicon
56
fork
atom
overview
issues
1
pulls
2
pipelines
wah
danabra.mov
5 months ago
8c5f23ff
423b3753
+127
-97
3 changed files
expand all
collapse all
unified
split
packages
website
package.json
src
components
Playground.tsx
pages
index.astro
+2
packages/website/package.json
···
11
"dependencies": {
12
"@astrojs/react": "^4.4.0",
13
"@tylex/emitter": "workspace:*",
0
0
14
"astro": "^5.14.1",
15
"json-stringify-pretty-compact": "^4.0.0",
16
"react": "^19.2.0",
···
11
"dependencies": {
12
"@astrojs/react": "^4.4.0",
13
"@tylex/emitter": "workspace:*",
14
+
"@typespec/bundler": "^0.4.4",
15
+
"@typespec/playground": "^0.11.0",
16
"astro": "^5.14.1",
17
"json-stringify-pretty-compact": "^4.0.0",
18
"react": "^19.2.0",
+32
-74
packages/website/src/components/Playground.tsx
···
1
-
import { useState } from 'react';
2
-
3
export default function Playground() {
4
-
const [tylexCode, setTylexCode] = useState(`@lexicon("1")
5
-
@nsid("app.bsky.feed.post")
6
-
namespace AppBskyFeedPost;
7
-
8
-
@record
9
-
@key("tid")
10
-
model Main {
11
-
@required text: string;
12
-
@required createdAt: datetime;
13
-
}`);
14
-
15
-
const [lexiconOutput] = useState('// Playground coming soon...');
16
-
17
return (
18
<div style={{
19
background: 'white',
20
borderRadius: '12px',
21
boxShadow: '0 4px 6px rgba(0, 0, 0, 0.05)',
22
overflow: 'hidden',
0
0
0
0
0
0
0
23
}}>
24
-
<div style={{
25
-
display: 'grid',
26
-
gridTemplateColumns: '1fr 1fr',
27
-
borderBottom: '2px solid #f8fafc',
28
-
background: '#fafafa',
29
-
}}>
30
-
<h3 style={{
31
-
padding: '1rem',
32
-
textAlign: 'center',
33
-
fontSize: '1rem',
34
-
color: '#64748b',
35
-
fontWeight: 600,
36
-
margin: 0,
37
-
}}>
38
-
Tylex Input
39
</h3>
40
-
<h3 style={{
41
-
padding: '1rem',
42
-
textAlign: 'center',
43
-
fontSize: '1rem',
44
-
color: '#64748b',
45
-
fontWeight: 600,
46
-
margin: 0,
47
-
}}>
48
-
Lexicon Output
49
-
</h3>
50
-
</div>
51
-
52
-
<div style={{
53
-
display: 'grid',
54
-
gridTemplateColumns: '1fr 1fr',
55
-
minHeight: '400px',
56
-
}}>
57
-
<div style={{ borderRight: '1px solid #f8fafc' }}>
58
-
<textarea
59
-
value={tylexCode}
60
-
onChange={(e) => setTylexCode(e.target.value)}
61
-
style={{
62
-
width: '100%',
63
-
height: '100%',
64
-
padding: '1.5rem',
65
-
border: 'none',
66
-
fontFamily: 'Monaco, Menlo, monospace',
67
-
fontSize: '0.875rem',
68
-
resize: 'none',
69
-
outline: 'none',
70
-
}}
71
-
placeholder="Enter Tylex code here..."
72
-
/>
73
-
</div>
74
-
75
-
<div style={{
76
-
padding: '1.5rem',
77
-
fontFamily: 'Monaco, Menlo, monospace',
78
-
fontSize: '0.875rem',
79
-
color: '#64748b',
80
-
overflowX: 'auto',
81
-
}}>
82
-
<pre style={{ margin: 0 }}>{lexiconOutput}</pre>
83
-
</div>
84
</div>
85
</div>
86
);
···
0
0
1
export default function Playground() {
0
0
0
0
0
0
0
0
0
0
0
0
0
2
return (
3
<div style={{
4
background: 'white',
5
borderRadius: '12px',
6
boxShadow: '0 4px 6px rgba(0, 0, 0, 0.05)',
7
overflow: 'hidden',
8
+
minHeight: '500px',
9
+
display: 'flex',
10
+
alignItems: 'center',
11
+
justifyContent: 'center',
12
+
padding: '2rem',
13
+
color: '#64748b',
14
+
fontFamily: 'system-ui, sans-serif',
15
}}>
16
+
<div style={{ textAlign: 'center', maxWidth: '600px' }}>
17
+
<h3 style={{ fontSize: '1.5rem', marginBottom: '1rem', color: '#1e293b', fontWeight: 700 }}>
18
+
Try it in the Playground
0
0
0
0
0
0
0
0
0
0
0
0
19
</h3>
20
+
<p style={{ fontSize: '1.125rem', marginBottom: '2rem', lineHeight: '1.6' }}>
21
+
Experience tylex with syntax highlighting, live compilation, and instant Lexicon output.
22
+
</p>
23
+
<a
24
+
href="http://localhost:5174"
25
+
target="_blank"
26
+
rel="noopener noreferrer"
27
+
style={{
28
+
display: 'inline-block',
29
+
padding: '0.875rem 2rem',
30
+
background: 'linear-gradient(135deg, #7a8ef7 0%, #9483f7 70%, #b87ed8 100%)',
31
+
color: 'white',
32
+
textDecoration: 'none',
33
+
borderRadius: '8px',
34
+
fontWeight: 700,
35
+
fontSize: '1.125rem',
36
+
boxShadow: '0 2px 4px rgba(122, 142, 247, 0.35), 0 3px 6px rgba(0, 0, 0, 0.1)',
37
+
transition: 'all 0.2s',
38
+
}}
39
+
>
40
+
Open Playground →
41
+
</a>
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
42
</div>
43
</div>
44
);
+93
-23
packages/website/src/pages/index.astro
···
130
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
131
<meta name="viewport" content="width=device-width" />
132
<meta name="generator" content={Astro.generator} />
133
-
<title>tylex – TypeSpec for AT Protocol Lexicons</title>
134
</head>
135
<body>
136
<div class="container">
···
198
</p>
199
200
<div class="hero-actions">
201
-
<a href="#install" class="install-cta">Install</a>
202
<a href="https://tangled.org/@danabra.mov/typlex" target="_blank" rel="noopener noreferrer" class="star-btn">
203
Read Documentation
204
</a>
···
231
232
<div class="separator"></div>
233
234
-
<section class="playground-section">
235
-
<h2>Playground</h2>
236
-
<Playground client:load />
237
-
</section>
238
-
239
-
<div class="separator"></div>
240
-
241
<section class="install-section" id="install">
242
<h2>Install</h2>
243
<div class="install-grid">
244
<div class="install-notice">
245
-
<p class="notice-text">This is an early alpha software. If you ship with borked lexicons, it’s not my fault.</p>
246
</div>
0
0
0
0
0
0
0
0
0
0
0
247
<div class="install-step">
248
<div class="step-number">1</div>
249
<div class="step-content">
···
283
<div class="step-content">
284
<h3>Set up VS Code</h3>
285
<p class="step-description">Install the <a href="https://typespec.io/docs/introduction/editor/vscode/" target="_blank" rel="noopener noreferrer">TypeSpec for VS Code extension</a> for syntax highlighting and IntelliSense.</p>
0
0
0
0
0
0
0
0
286
</div>
287
</div>
288
</div>
···
718
719
.install-step {
720
position: relative;
0
0
0
0
0
0
0
721
}
722
723
.step-number {
724
-
position: absolute;
725
-
left: -3.5rem;
726
-
top: 0.125rem;
727
width: 2.25rem;
728
height: 2.25rem;
729
background: linear-gradient(135deg, #7a8ef7, #ff85c1);
730
color: white;
731
border-radius: 50%;
732
-
display: flex;
733
-
align-items: center;
734
-
justify-content: center;
735
font-weight: 700;
736
font-size: 0.9375rem;
0
737
}
738
739
.step-content {
740
width: 100%;
741
}
742
0
0
0
0
0
0
0
0
0
0
0
0
743
.step-content h3 {
744
font-size: 1.25rem;
745
margin: 0 0 1.25rem 0;
···
822
823
.install-grid {
824
gap: 3.5rem;
825
-
}
826
-
827
-
.step-number {
828
-
left: -4rem;
829
-
width: 2.5rem;
830
-
height: 2.5rem;
831
-
font-size: 1rem;
832
}
833
834
.step-content h3 {
···
1041
1042
.playground-section {
1043
margin: 0;
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1044
}
1045
1046
footer {
···
130
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
131
<meta name="viewport" content="width=device-width" />
132
<meta name="generator" content={Astro.generator} />
133
+
<title>tylex – TypeSpec for AT protocol Lexicons</title>
134
</head>
135
<body>
136
<div class="container">
···
198
</p>
199
200
<div class="hero-actions">
201
+
<a href="#install" class="install-cta">Try It</a>
202
<a href="https://tangled.org/@danabra.mov/typlex" target="_blank" rel="noopener noreferrer" class="star-btn">
203
Read Documentation
204
</a>
···
231
232
<div class="separator"></div>
233
0
0
0
0
0
0
0
234
<section class="install-section" id="install">
235
<h2>Install</h2>
236
<div class="install-grid">
237
<div class="install-notice">
238
+
<p class="notice-text">This is an early-stage experiment. There are bugs. You must verify the output!</p>
239
</div>
240
+
<div class="install-step playground-step">
241
+
<div class="step-number">0</div>
242
+
<div class="step-content">
243
+
<h3>Try the playground</h3>
244
+
<p class="step-description">Experiment with typelex in your browser before installing.</p>
245
+
<a href="http://localhost:5174" target="_blank" rel="noopener noreferrer" class="playground-button">
246
+
Open Playground
247
+
</a>
248
+
</div>
249
+
</div>
250
+
251
<div class="install-step">
252
<div class="step-number">1</div>
253
<div class="step-content">
···
287
<div class="step-content">
288
<h3>Set up VS Code</h3>
289
<p class="step-description">Install the <a href="https://typespec.io/docs/introduction/editor/vscode/" target="_blank" rel="noopener noreferrer">TypeSpec for VS Code extension</a> for syntax highlighting and IntelliSense.</p>
290
+
</div>
291
+
</div>
292
+
293
+
<div class="install-step">
294
+
<div class="step-number">5</div>
295
+
<div class="step-content">
296
+
<h3>Read the docs</h3>
297
+
<p class="step-description">Check out the <a href="https://tangled.org/@danabra.mov/typlex" target="_blank" rel="noopener noreferrer">documentation</a> to learn more about Typelex syntax and features.</p>
298
</div>
299
</div>
300
</div>
···
730
731
.install-step {
732
position: relative;
733
+
overflow: hidden;
734
+
}
735
+
736
+
@media (min-width: 768px) {
737
+
.install-step {
738
+
overflow: visible;
739
+
}
740
}
741
742
.step-number {
743
+
display: inline-flex;
744
+
align-items: center;
745
+
justify-content: center;
746
width: 2.25rem;
747
height: 2.25rem;
748
background: linear-gradient(135deg, #7a8ef7, #ff85c1);
749
color: white;
750
border-radius: 50%;
0
0
0
751
font-weight: 700;
752
font-size: 0.9375rem;
753
+
margin-bottom: 1rem;
754
}
755
756
.step-content {
757
width: 100%;
758
}
759
760
+
@media (min-width: 768px) {
761
+
.step-number {
762
+
position: absolute;
763
+
left: -4rem;
764
+
top: 0.125rem;
765
+
width: 2.5rem;
766
+
height: 2.5rem;
767
+
font-size: 1rem;
768
+
margin-bottom: 0;
769
+
}
770
+
}
771
+
772
.step-content h3 {
773
font-size: 1.25rem;
774
margin: 0 0 1.25rem 0;
···
851
852
.install-grid {
853
gap: 3.5rem;
0
0
0
0
0
0
0
854
}
855
856
.step-content h3 {
···
1063
1064
.playground-section {
1065
margin: 0;
1066
+
}
1067
+
1068
+
.playground-button {
1069
+
display: inline-block;
1070
+
margin-top: 1.25rem;
1071
+
padding: 0.875rem 2rem;
1072
+
background: linear-gradient(135deg, #7a8ef7 0%, #9483f7 70%, #b87ed8 100%);
1073
+
color: white;
1074
+
text-decoration: none;
1075
+
border-radius: 8px;
1076
+
font-weight: 700;
1077
+
font-size: 1.0625rem;
1078
+
letter-spacing: 0.01em;
1079
+
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
1080
+
box-shadow:
1081
+
0 1px 0 0 rgba(255, 255, 255, 0.25) inset,
1082
+
0 -1px 0 0 rgba(0, 0, 0, 0.1) inset,
1083
+
0 0 0 1px rgba(122, 142, 247, 0.3),
1084
+
0 2px 4px rgba(122, 142, 247, 0.35),
1085
+
0 3px 6px rgba(0, 0, 0, 0.1);
1086
+
border: none;
1087
+
}
1088
+
1089
+
.playground-button:hover {
1090
+
background: linear-gradient(135deg, #7384e7 0%, #8d7ce7 70%, #b175d1 100%);
1091
+
box-shadow:
1092
+
0 1px 0 0 rgba(255, 255, 255, 0.3) inset,
1093
+
0 -1px 0 0 rgba(0, 0, 0, 0.12) inset,
1094
+
0 0 0 1px rgba(122, 142, 247, 0.4),
1095
+
0 3px 6px rgba(122, 142, 247, 0.4),
1096
+
0 4px 8px rgba(0, 0, 0, 0.12);
1097
+
transform: translateY(-1px);
1098
+
}
1099
+
1100
+
.playground-button:active {
1101
+
background: linear-gradient(135deg, #6a7ee5 0%, #8473e5 70%, #a86ec8 100%);
1102
+
box-shadow:
1103
+
0 0 0 1px rgba(122, 142, 247, 0.5),
1104
+
0 1px 2px rgba(0, 0, 0, 0.2) inset,
1105
+
0 2px 4px rgba(0, 0, 0, 0.15);
1106
+
transform: translateY(1px);
1107
+
}
1108
+
1109
+
@media (min-width: 768px) {
1110
+
.playground-button {
1111
+
font-size: 1.125rem;
1112
+
padding: 1rem 2.5rem;
1113
+
}
1114
}
1115
1116
footer {