Compare commits

474 Commits

Author SHA1 Message Date
Josh Soref
bf5d7d84c9 Merge ecfd50f991 into 3b92768480 2025-01-29 00:06:27 -05:00
Josh Soref
ecfd50f991 spelling: yesterday
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
718ea629a5 spelling: written
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
bb79879779 spelling: workarounds
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
a33fc19e8e spelling: workaround
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
af088d08a6 spelling: within
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
7049285694 spelling: with
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
4f5fbed978 spelling: window
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
be5dc944b3 spelling: whoami
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
fed3c7b83f spelling: whether
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
09c53ebd36 spelling: where
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
b778cd6794 spelling: whenever
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
8ee2a95771 spelling: when
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
7885833fe8 spelling: watchbands
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
3bde9c1ab3 spelling: wakeup
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
7499ab128b spelling: visible
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
36c9aac1f5 spelling: violations
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
39c1e7b34f spelling: vertically
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
159e6cc255 spelling: vertical
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
0098e27ba5 spelling: version
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
c1e8ef32bd spelling: variable
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
d37fe946e1 spelling: value
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
a679c3d713 spelling: use
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
58d50a77e5 spelling: unused
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
03c66ad51e spelling: unsuccessful
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
0f74b405d0 spelling: unsubscribed
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
445eb1471b spelling: unsubscribe
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
c32466e61e spelling: unnecessarily
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
523e6cf397 spelling: unnamed
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
82ee3a22ea spelling: unless
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
f6d5f8ce95 spelling: uninitialized
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
e5fbc9e67e spelling: unfortunately
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
76f3819b39 spelling: typical
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
e38db99b9d spelling: twelfth
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
762142cebc spelling: truncate
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
cb44bb9967 spelling: triggered
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
cceec5ae32 spelling: tries
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
be54304b88 spelling: transparent
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
4be1d9c8ac spelling: transparency
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
58c22748cc spelling: transimpedance
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
b7297fd9f4 spelling: transformation
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
120c7e248c spelling: traditional
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
e53dc17016 spelling: traceability
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
7594b4c878 spelling: today
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
913fa41c99 spelling: to
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
f257b7ae1f spelling: timestamp
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
994d10f5df spelling: timeouts
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
4ba1278010 spelling: threshold
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
9485f1e908 spelling: this
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
79e6f0cf2f spelling: third
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:29 -05:00
Josh Soref
374b10c683 spelling: thickness
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
d09aca0a02 spelling: the
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
34b2a18fcc spelling: that
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
9077267ceb spelling: than
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
5cb061cff5 spelling: terminator
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
ccca8fddcd spelling: targeting
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
c477e689c9 spelling: targeted
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
53b74221f2 spelling: system
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
979061a875 spelling: synchronizing
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
0a909d7a50 spelling: synchronization
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
b32d22a6d2 spelling: surprisingly
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
202215e86c spelling: surprise
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
6ba090d3ce spelling: suppressing
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
f2b037375c spelling: supports
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
a169a706b7 spelling: supported
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
bcf5e6d9f9 spelling: superseded
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
aacf4a9ab6 spelling: suddenly
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
eadb5ca422 spelling: successive
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
9e89559322 spelling: successfully
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
aee29ca34b spelling: successful
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
56b1584352 spelling: success
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
9bf2e4c8dc spelling: succeeds
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
836341f13b spelling: subtracted
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
85257fc5c4 spelling: subtract
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
da5daef528 spelling: subscription
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
f7e65496ba spelling: structured
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
06296179d9 spelling: structure
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
f14d9da22e spelling: strongly
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
55d1f98745 spelling: stress
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
edb0a78b0a spelling: strength
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
c2cf2fd848 spelling: straight
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
56f907ed6b spelling: status
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
6fc8ed0772 spelling: stabilized
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
88ce796b6c spelling: stabilization
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
cd8520acbf spelling: spectral
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
9e6d15a209 spelling: specifier
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
848a68c241 spelling: specific
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
faf96c3ee2 spelling: space
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
94240d33f2 spelling: smartstraps
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
ced5200233 spelling: size
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
9dc350a663 spelling: situations
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
0666aa0089 spelling: simultaneously
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
608aac6e0b spelling: simultaneous
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
cbbaeba03c spelling: similarly
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
b8c84e077c spelling: shut
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
47319ea499 spelling: shrunk
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
1d3a78f7b6 spelling: should
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
5cb667ae61 spelling: shipping
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
9ecddce587 spelling: setup
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
fc2f5a982e spelling: session
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
6dbbbee3e2 spelling: seriously
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
c5495ecbc5 spelling: serialized
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
927251a776 spelling: separator
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:28 -05:00
Josh Soref
586db5b942 spelling: separate
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
394c11d071 spelling: sentinel
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
b33c3a748e spelling: semaphore
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
acad6e8efa spelling: section
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
eddc390e76 spelling: secondary
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
16f151faa2 spelling: scroll
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
c29f9fee52 spelling: schedule
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
173bdadc3a spelling: scanlines
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
93135f6c5a spelling: saturday
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
3faa3c0faf spelling: robining
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
99187c5d4e spelling: returns
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
fa22912737 spelling: retrieving
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
466e7f7505 spelling: retrieves
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
656ba98a40 spelling: retrieve
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
2062536f26 spelling: retrieval
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
c42dfbcdfc spelling: response
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
0a6167953f spelling: respond
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
0423ca826f spelling: respectively
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
5d1081bc13 spelling: resources
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
3d85a9cb3b spelling: resource
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
0d9e35fad1 spelling: rescheduling
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
71e60e3b87 spelling: requirement
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
1732aa321b spelling: request
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
6590c67a88 spelling: represented
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
e2cad1d2fb spelling: representation
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
1ac3b3ccc6 spelling: reopened
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
d0a5f03b93 spelling: remnants
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
d9f57de352 spelling: remaining
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
cfea0fc3c2 spelling: reload
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
0c55d530ac spelling: relative
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
7d745d4c61 spelling: relation
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
bc2c2393d7 spelling: regular
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
5f98552305 spelling: registry
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
fc797cd252 spelling: registering
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
3b92b65db8 spelling: referring
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
c7851d5745 spelling: reentrancy
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
1b10188be4 spelling: receiving
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
9f4d934ec4 spelling: received
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
a0222e963c spelling: receive
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
a58187577d spelling: reauth
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
7420fcb525 spelling: quicklaunch
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
d6ff98373d spelling: quadrant
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
d56fb48114 spelling: provider
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
47af5bd094 spelling: protocol
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
110e0fda31 spelling: property
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
866f4f003f spelling: propagate
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
5ed0a14ec3 spelling: programmatically
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
f28754372d spelling: program
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
32e4e88d18 spelling: processor
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
4329f3eeb6 spelling: processing
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
8c57480b2a spelling: processed
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
060d7cb58d spelling: process
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
67713b7888 spelling: probability
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
e35b142f68 spelling: privileged
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
d4d8ed5147 spelling: priority
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
cd127de7e0 spelling: prioritized
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:27 -05:00
Josh Soref
d7c8734211 spelling: previously
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
d527ad11b6 spelling: previous
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
4cad9181a1 spelling: pretend
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
8ca8cffcc3 spelling: preexisting
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
815e361d75 spelling: precise
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
e3602b52fc spelling: potential
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
ed1e3c836b spelling: possible
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
ab86d94493 spelling: possibility
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
27cbe4bcba spelling: point
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
0887be2c39 spelling: platform
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
7d8b2dc7aa spelling: peripheral
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
dd02b29b2a spelling: periodically
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
33edf22381 spelling: performing
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
fcfff639f7 spelling: perceived
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
52580daf82 spelling: pathological
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
d98fd94906 spelling: passed
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
46910d0b3d spelling: partway
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
8b9b5997fa spelling: parameter
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
dc15069898 spelling: param
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
3343c3a8b6 spelling: palettized
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
bd132b4003 spelling: palette
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
0a17a4a67c spelling: pairability
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
3572d429b2 spelling: overridden
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
db1840c0f5 spelling: overlap
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
1e3f63fe26 spelling: overflow
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
b2075d3b2a spelling: overarching
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
24100e233b spelling: output
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
2e769148e9 spelling: other
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
92b055a0c4 spelling: orphans
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
f44e5e50e9 spelling: original
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
13de07fe70 spelling: or
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
fce4b36689 spelling: options
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
329160068e spelling: optional
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
9af84e083f spelling: opt-in
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
a9dd33cea2 spelling: opposed
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
0c55874b21 spelling: ongoing
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
a967d8f275 spelling: onboard
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
651f82f9c5 spelling: olson
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
b7b8abcff7 spelling: offset
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
6fcb2ed60e spelling: occurs
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
3f55864a85 spelling: occurring
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
9cf1456fff spelling: occurrences
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
76f2f9643f spelling: occurrence
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
3d34684548 spelling: occurred
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
0f0c1cca12 spelling: objects
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
ca40ee484d spelling: obfuscated
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
489a1d54cd spelling: notifications
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:26 -05:00
Josh Soref
c2e8d1d0ce spelling: notification
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
d9ec8a3438 spelling: not
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
fa235e9c73 spelling: normalized
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
c2f7961747 spelling: nonexistent
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
9985f1fdf3 spelling: next
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
56f2f72c43 spelling: necessary
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
808be075ae spelling: necessarily
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
77b62896d8 spelling: nearest
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
47c7c80798 spelling: multiplies
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
65efdcd686 spelling: multiplication
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
723223e7a9 spelling: multiple
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
7898b0c0ed spelling: movement
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
d755d296fc spelling: more
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
607d0d33b8 spelling: mirrored
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
1478a09825 spelling: minimum
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
13f4c1949e spelling: minimized
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
8db950eef8 spelling: milliseconds
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
2d73a5db2a spelling: metadata
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
448406972a spelling: messages
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
1e36e9376c spelling: memory
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
3103346331 spelling: measurement
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
14c0197dc2 spelling: many, many,
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
04822e0ea5 spelling: malformed
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
0527df21d1 spelling: makes
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
f8142aaa56 spelling: macos
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
dff797266c spelling: lowest
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
df09a16db5 spelling: load
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
4e17c71160 spelling: limit
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
efb437bff4 spelling: light
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
9a74f51086 spelling: lifecycle
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
2ca6621c38 spelling: length
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
7ee4164362 spelling: leaving
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
087fa58d43 spelling: layer (?)
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
a503372d8d spelling: latest
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
f26b13d697 spelling: large
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
cb0ad69261 spelling: kernel
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
c01e9cf70d spelling: javascript
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
4806c06f10 spelling: its
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
a35061eaf8 spelling: iteration
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
d78f6df080 spelling: iterating
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
2437efdba9 spelling: issues
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
57fd1766c0 spelling: invert
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
1414ea00a4 spelling: invalid
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
c0f95d06d3 spelling: internal
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
ef3b42207f spelling: intentionally
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
1ecb14eb8a spelling: integrity
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
ee41f88dad spelling: integer
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
ab2d0b338a spelling: instantiated
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
ec3d12929e spelling: instantiate
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
24dd728cf1 spelling: inspired by
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
8d841c5e2e spelling: insert
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
6e17914ae0 spelling: insensitive
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
c592d79230 spelling: inner
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
cb9fe3152f spelling: initiator
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
714282660f spelling: initiated
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
1e7f815c39 spelling: initiate
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:25 -05:00
Josh Soref
e63c8c0b83 spelling: initializes
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
cf9a5cb367 spelling: initialize
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
4ec73561f9 spelling: initialization
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
42ff2a4a3e spelling: initial
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
9ab4efb8b8 spelling: infinite
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
9fd89172fc spelling: inertial
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
255d697f1b spelling: indices
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
ae06af83ac spelling: indicates
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
294f626792 spelling: independent
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
423a462ce0 spelling: increment
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
191f0be9a7 spelling: includes
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
8ce07c9151 spelling: implicitly
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
fdc40c6e40 spelling: implementation
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
e291b6726e spelling: ignore
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
2efa9cc170 spelling: id
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
7128e60f76 spelling: history
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
d6faaacb44 spelling: highlight
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
10dee72f9e spelling: header
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
1fcda4287c spelling: have
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
d52c94a0ed spelling: hardware
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
69269d8bf1 spelling: happened
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
7e0b951d8e spelling: handlers
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
07248ac67e spelling: handler
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
01a349d9d4 spelling: halves
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
28e0019973 spelling: guaranteed
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
bab9301a3a spelling: greater
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
4816a8890b spelling: graphics
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
a57a2f6fea spelling: grab
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
8513038ad2 spelling: glyphs
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
30c49030d1 spelling: global
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
8ac24bd4f5 spelling: geometry
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
5351cd6f1c spelling: generic
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
adb0257e93 spelling: gaussian
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
91e869b7a5 spelling: fuzzed
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
11d05ba281 spelling: function
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
3c336ea7f5 spelling: framebuffer
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
0073a89149 spelling: fragments
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
6f28530f90 spelling: fragmentation
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
e7c5c587ae spelling: fractional
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
e479411f59 spelling: forward
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
937ef82130 spelling: forever
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
0adb006678 spelling: for
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
390d433bf8 spelling: following
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
22e6f64653 spelling: firmware
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
c4b4244b2d spelling: find
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
583bd2a005 spelling: filtering
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
5ea72eb54a spelling: filesystem
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
f7145c9739 spelling: faster
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
9a28b928ad spelling: false
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
bd5b200a81 spelling: facilitate
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
0fe878c043 spelling: extensions
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
ecb5dae4ef spelling: exponential
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
f5e9b300f2 spelling: explicitly
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:24 -05:00
Josh Soref
1f430457c1 spelling: expiration
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:23 -05:00
Josh Soref
cb8f7b7fc1 spelling: expected
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:23 -05:00
Josh Soref
0de0ee0d68 spelling: existing
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:23 -05:00
Josh Soref
874cd587c2 spelling: existence
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:23 -05:00
Josh Soref
1c9c779192 spelling: execution
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:23 -05:00
Josh Soref
0a46a061ff spelling: exclude
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:23 -05:00
Josh Soref
ed0bfa91da spelling: exceed
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:23 -05:00
Josh Soref
fa4eee1991 spelling: example
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:23 -05:00
Josh Soref
8231962ed3 spelling: every
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:23 -05:00
Josh Soref
fbdf1536ff spelling: every time
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:23 -05:00
Josh Soref
a1f463ea99 spelling: erroneous
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:23 -05:00
Josh Soref
e33cd4add1 spelling: erasable
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:23 -05:00
Josh Soref
11a46154bc spelling: equal
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:23 -05:00
Josh Soref
0cf7d4d8e4 spelling: entry
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-29 00:03:23 -05:00
Josh Soref
732a680ad8 spelling: enter
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
16883e83c6 spelling: endpoints
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
6c88d0de02 spelling: encryption
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
436c0cada7 spelling: encrypt
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
f6321cfb9a spelling: empty
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
1a6f00e08f spelling: elapsed
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
42b59e79fb spelling: either
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
3237d40a97 spelling: earliest
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
ef22f1e4a9 spelling: each other
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
6defdc6ebb spelling: during
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
5d8096f8f1 spelling: doesn't
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
f9e2379cdb spelling: does (?) not
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
a6a27be9a5 spelling: display
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
0ad05d3c3d spelling: dismissed
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
10bc03cd17 spelling: discover
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
dc649bd184 spelling: disappear
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
f8d6aad3e7 spelling: disabled
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
a2e8bce4a9 spelling: differently
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
4909e42a4f spelling: differentiate
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
45c881e347 spelling: destroy
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
2e9824bf45 spelling: describing
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
5c8207c8c2 spelling: described
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
e3c66a23c7 spelling: dereference
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
ebfec3118d spelling: dependent
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
924f309bff spelling: delimited
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
2f60d53f62 spelling: deinitialize
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
2b8a8dcfdd spelling: degrees
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
506c882fda spelling: definitions
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
a0b9ef4851 spelling: definition
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
2d7ac814c6 spelling: decrement
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
621151ebd1 spelling: custom
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
435ef6ba65 spelling: currently
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
e39d9fc773 spelling: current
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
b92a7363d5 spelling: create
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
89894ab4f1 spelling: couldn't
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
eef1e8dbd6 spelling: corruption
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:35 -05:00
Josh Soref
4824c55fed spelling: corrupt
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
21884a76f2 spelling: corresponds
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
deffe7f483 spelling: corresponding
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
a989875686 spelling: correctly
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
1cceb1206d spelling: correct
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
837f87c424 spelling: corner
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
2a7d5ceaa4 spelling: coordinates
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
e0d7a82844 spelling: coordinate
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
82c69d2f5d spelling: convenience
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
c54407bb82 spelling: continuously
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
e3dd54fda9 spelling: contiguous
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
74d9fc2ef5 spelling: consumer
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
5f8d2a47aa spelling: constraint
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
a29c01bf00 spelling: connection
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
bd2c2ad356 spelling: conjunction
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
9d85fb19ba spelling: confirm
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
15d5df83b8 spelling: configurable
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
a40b21060d spelling: concatenating
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
e3c1fb279e spelling: compositor
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
f21d4da40f spelling: compositing
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
6d6b22b697 spelling: completing
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
272237b048 spelling: complete
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
9ac1fb003d spelling: compensation
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
0e66fca4ed spelling: compensate
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
d9cbe55fed spelling: compatible
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
6dd10b1640 spelling: compatibility
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
2967f60ffc spelling: commit
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
9d9edae49f spelling: commands
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
81b2d104a6 spelling: command
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
726d92f563 spelling: coming
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
d8ade6b665 spelling: coefficients
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
ae61face91 spelling: client
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
9f095745da spelling: classic
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
0b140893f9 spelling: circle
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
d3175992ea spelling: chunksize
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
27d14ba72a spelling: check
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
348660fb1e spelling: characters
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
ee449fd875 spelling: characteristic
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
e3df3055e2 spelling: certification
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
5dfb79c189 spelling: certain
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
4f43035df7 spelling: cassette
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
30232b4c27 spelling: capacity
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
f7cac0ad9b spelling: cannot
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
04ba22ffb9 spelling: canned
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
888911aaa9 spelling: can
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:32:34 -05:00
Josh Soref
9c5fc488e0 spelling: called
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:19:00 -05:00
Josh Soref
4a26ea9f66 spelling: callback
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:19:00 -05:00
Josh Soref
4011cdd2c3 spelling: call
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:19:00 -05:00
Josh Soref
71513f263b spelling: cacheable
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:19:00 -05:00
Josh Soref
5489a4c0d3 spelling: cache
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:19:00 -05:00
Josh Soref
0248c81c86 spelling: building
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:19:00 -05:00
Josh Soref
a40097521c spelling: boundary
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:19:00 -05:00
Josh Soref
53cdea8d3d spelling: boundaries
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:19:00 -05:00
Josh Soref
e681b24ea3 spelling: bluetooth
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:19:00 -05:00
Josh Soref
3dc43a4c1b spelling: bizarre
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:19:00 -05:00
Josh Soref
2e05d7addb spelling: birthdays
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:19:00 -05:00
Josh Soref
0ab43a028e spelling: bidirectional
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:19:00 -05:00
Josh Soref
dc157413ef spelling: between
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:19:00 -05:00
Josh Soref
de2ef95804 spelling: beginning
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:19:00 -05:00
Josh Soref
5a7fdca2e4 spelling: before
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:19:00 -05:00
Josh Soref
4c1819019d spelling: because
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:19:00 -05:00
Josh Soref
7bccc39af7 spelling: bandwidth
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:19:00 -05:00
Josh Soref
6dd9f2a7ed spelling: balamurugan
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:19:00 -05:00
Josh Soref
fc4b5a3b02 spelling: available
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:19:00 -05:00
Josh Soref
0af48bf2c5 spelling: attribute
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:19:00 -05:00
Josh Soref
dc6250106b spelling: attempt
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:18:59 -05:00
Josh Soref
87e43e8978 spelling: asynchronous
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:18:59 -05:00
Josh Soref
06a79bb396 spelling: asteroid
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:18:59 -05:00
Josh Soref
faec942996 spelling: artificially
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:18:59 -05:00
Josh Soref
7bd5bbfeb1 spelling: arguments
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:18:59 -05:00
Josh Soref
b0efa9eb1a spelling: are
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:18:59 -05:00
Josh Soref
da8071bdb5 spelling: architecture
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:18:59 -05:00
Josh Soref
1114914d33 spelling: arbitrarily
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:18:59 -05:00
Josh Soref
2529de015f spelling: appropriate
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:18:59 -05:00
Josh Soref
852098a92e spelling: anyways
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:18:59 -05:00
Josh Soref
85e2476bcf spelling: another size is
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 21:18:59 -05:00
Josh Soref
575b358aa5 spelling: anonymous
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
bbcf3ec07d spelling: animation
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
b8d261b2e0 spelling: android
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
05d09de90b spelling: and
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
0bef7743f6 spelling: and restarted
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
17765dce27 spelling: and bounds
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
4ed89321ff spelling: always
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
405717f0de spelling: already
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
e02cd968c2 spelling: alignment
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
d12fb4b380 spelling: align
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
49b0f1f668 spelling: algorithm
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
916a84faca spelling: aggressive
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
3e4d224e8b spelling: after all
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
03349f2d2b spelling: advertisement
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
9ef3483674 spelling: address
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
2df7d018dd spelling: additional
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
395e6d3b22 spelling: actually
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
2e283181ba spelling: activity
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
daf0574d29 spelling: activities
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
6d23cc16b3 spelling: actionable
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
a5ba1d6026 spelling: action
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
80421e092f spelling: acquire
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:32 -05:00
Josh Soref
572925d9fb spelling: achieve
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:31 -05:00
Josh Soref
2a9f359b51 spelling: accuracy
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:31 -05:00
Josh Soref
d2e293116f spelling: according
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:31 -05:00
Josh Soref
643abbfcf3 spelling: accompanied
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:31 -05:00
Josh Soref
b60d61e5e1 spelling: accommodate
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:31 -05:00
Josh Soref
eb5cbb2f63 spelling: accessible
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 15:04:31 -05:00
Josh Soref
2a7756f365 spelling: accesses
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 13:30:20 -05:00
Josh Soref
21eca690fa spelling: access
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 13:30:20 -05:00
Josh Soref
d2219b299e spelling: acceptable
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 13:30:20 -05:00
Josh Soref
605fe7756e spelling: accelerometer
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 13:30:20 -05:00
Josh Soref
4ed801eaf9 spelling: a
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-01-28 11:16:34 -05:00
2095 changed files with 1089 additions and 288773 deletions

View File

@@ -558,7 +558,7 @@ jerry_size_t jerry_object_to_string_to_utf8_char_buffer(const jerry_value_t obje
return len;
}
// FIXME: PBL-43551 Propery CESU-8 => UTF-8 conversion.
// FIXME: PBL-43551 Property CESU-8 => UTF-8 conversion.
jerry_size_t jerry_object_to_string_to_char_buffer(const jerry_value_t object,
jerry_char_t *buffer_p,
jerry_size_t buffer_size) {

View File

@@ -160,7 +160,7 @@ static bool prv_get_resource(uint32_t resource_id, Resource *res) {
if ((entry.resource_id != resource_id) ||
(entry.length == 0)) {
// empty resource
printf("%s: Invalid resourcel for %d\n", __FILE__, resource_id);
printf("%s: Invalid resource for %d\n", __FILE__, resource_id);
return false;
}

View File

@@ -22,7 +22,7 @@
#include "resource/resource.h"
// transformed to int to avoid surpises between C->JS
// transformed to int to avoid surprises between C->JS
typedef int (*ResourceReadCb)(int offset, uint8_t *buf, int num_bytes);
typedef int (*ResourceGetSizeCb)(void);

View File

@@ -28,7 +28,7 @@ namespace std {
}
/* This analyzer suffers from the major limitation that most of the mutexes in Pebble are globals,
* so all symbols and MemRegions refering to the mutexes are invalidated every time an unknown
* so all symbols and MemRegions referring to the mutexes are invalidated every time an unknown
* function is called. This analyzer instead associates mutexes with the declaration of their
* variables, which has the obvious limitation of not catching when mutexes are passed as
* arguments (which fortunately never? happens in pebble).

View File

@@ -1,12 +0,0 @@
URL=http://developer.pebble.com
HTTPS_URL=https://developer.pebble.com
EXTERNAL_SERVER=https://developer-api.getpebble.com
DOCS_URL=
ALGOLIA_APP_ID=
ALGOLIA_API_KEY=
ALGOLIA_SEARCH_KEY=
ALGOLIA_PREFIX=devsite-dev-
GOOGLE_ANALYTICS=
ROLLBAR_CLIENT_TOKEN=
RACK_ENV=development
SKIP_DOCS=false

12
devsite/.gitignore vendored
View File

@@ -1,12 +0,0 @@
__public__
.sass-cache/
.env
tmp/
source/stylesheets/
log/
.bundle/
coverage/
node_modules/
vendor/
.ruby-version
.jekyll-metadata

View File

View File

@@ -1,155 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This is the scss-lint configuration file for the Pebble Developer Site.
linters:
BorderZero:
enabled: true
CapitalizationInSelector:
enabled: true
ColorKeyword:
enabled: true
Comment:
enabled: true
DebugStatement:
enabled: true
DeclarationOrder:
enabled: true
DuplicateProperty:
enabled: true
ElsePlacement:
enabled: true
style: new_line
EmptyLineBetweenBlocks:
enabled: true
ignore_single_line_blocks: true
EmptyRule:
enabled: true
FinalNewline:
enabled: true
present: true
HexLength:
enabled: true
style: short
HexNotation:
enabled: true
style: lowercase
HexValidation:
enabled: true
IdWithExtraneousSelector:
enabled: true
Indentation:
enabled: true
character: space
width: 2
LeadingZero:
enabled: true
style: include_zero
MergeableSelector:
enabled: true
force_nesting: true
NameFormat:
enabled: true
convention: BEM
PlaceholderInExtend:
enabled: true
PropertySortOrder:
enabled: true
ignore_unspecified: false
PropertySpelling:
enabled: true
extra_properties: []
SelectorDepth:
enabled: true
max_depth: 3
Shorthand:
enabled: true
SingleLinePerProperty:
enabled: true
allow_single_line_rule_sets: true
SingleLinePerSelector:
enabled: true
SpaceAfterComma:
enabled: true
SpaceAfterPropertyColon:
enabled: true
style: one_space
SpaceAfterPropertyName:
enabled: true
SpaceBeforeBrace:
enabled: true
allow_single_line_padding: false
SpaceBetweenParens:
enabled: true
spaces: 0
StringQuotes:
enabled: true
style: single_quotes
TrailingSemicolon:
enabled: true
UnnecessaryMantissa:
enabled: true
UnnecessaryParentReference:
enabled: true
UrlFormat:
enabled: true
UrlQuotes:
enabled: true
ZeroUnit:
enabled: true
Compass::*:
enabled: false
SelectorFormat:
enabled: true
convention: hyphenated_BEM

View File

@@ -1,44 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
source 'https://rubygems.org'
ruby '2.2.4'
gem 'slugize', '>= 0.0.3'
gem 'jekyll', '>= 3.0.3'
gem 'jekyll-paginate'
gem 'bundler', '>= 1.7.9'
gem 'rack', '< 1.6.0'
gem 'rack-contrib', '>= 1.2.0'
gem 'nokogiri', '>= 1.6.3.1'
gem 'algoliasearch', '>= 1.6.1'
gem 'htmlentities', '>= 4.3.2'
gem 'rubyzip', '>=1.1.6'
gem 'dotenv', '>= 0.11.1'
gem 'newrelic_rpm', '>= 3.9.8.273'
gem 'rack-wwwhisper', '>= 1.0'
gem 'uglifier', '>= 2.7.0'
gem 'googlestaticmap', '>= 1.2.2'
gem 'rack-rewrite', '>= 1.5.0'
gem 'rack-ssl-enforcer', '>= 0.2.9'
gem 'rack-xframe-options', '>= 0.1.2'
gem 'rack-host-redirect'
gem 'pygments.rb'
gem 'redcarpet'
group :development, :test do
gem 'rspec', '>= 3.1.0'
gem 'simplecov', '>= 0.9.1'
gem 'rubocop', '>= 0.28.0'
end

View File

@@ -1,138 +0,0 @@
GEM
remote: https://rubygems.org/
specs:
addressable (2.3.8)
algoliasearch (1.7.0)
httpclient (~> 2.4)
json (>= 1.5.1)
ast (2.2.0)
colorator (0.1)
diff-lcs (1.2.5)
docile (1.1.5)
dotenv (2.1.0)
execjs (2.6.0)
ffi (1.9.10)
git-version-bump (0.15.1)
googlestaticmap (1.2.2)
htmlentities (4.3.4)
httpclient (2.7.1)
jekyll (3.1.2)
colorator (~> 0.1)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 1.1)
kramdown (~> 1.3)
liquid (~> 3.0)
mercenary (~> 0.3.3)
rouge (~> 1.7)
safe_yaml (~> 1.0)
jekyll-paginate (1.1.0)
jekyll-sass-converter (1.4.0)
sass (~> 3.4)
jekyll-watch (1.3.1)
listen (~> 3.0)
json (1.8.3)
kramdown (1.9.0)
liquid (3.0.6)
listen (3.0.6)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9.7)
mercenary (0.3.5)
mini_portile2 (2.0.0)
net-http-persistent (2.9.4)
newrelic_rpm (3.14.2.312)
nokogiri (1.6.7.2)
mini_portile2 (~> 2.0.0.rc2)
parser (2.3.0.2)
ast (~> 2.2)
posix-spawn (0.3.11)
powerpack (0.1.1)
pygments.rb (0.6.3)
posix-spawn (~> 0.3.6)
yajl-ruby (~> 1.2.0)
rack (1.5.5)
rack-contrib (1.4.0)
git-version-bump (~> 0.15)
rack (~> 1.4)
rack-host-redirect (1.2.1)
rack
rack-rewrite (1.5.1)
rack-ssl-enforcer (0.2.9)
rack-wwwhisper (1.1.9)
addressable (~> 2.0)
net-http-persistent
rack (~> 1.0)
rack-xframe-options (0.1.2)
rack (>= 0.9.1)
rainbow (2.1.0)
rb-fsevent (0.9.7)
rb-inotify (0.9.7)
ffi (>= 0.5.0)
redcarpet (3.3.4)
rouge (1.10.1)
rspec (3.4.0)
rspec-core (~> 3.4.0)
rspec-expectations (~> 3.4.0)
rspec-mocks (~> 3.4.0)
rspec-core (3.4.2)
rspec-support (~> 3.4.0)
rspec-expectations (3.4.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.4.0)
rspec-mocks (3.4.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.4.0)
rspec-support (3.4.1)
rubocop (0.36.0)
parser (>= 2.3.0.0, < 3.0)
powerpack (~> 0.1)
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.7)
ruby-progressbar (1.7.5)
rubyzip (1.1.7)
safe_yaml (1.0.4)
sass (3.4.21)
simplecov (0.11.1)
docile (~> 1.1.0)
json (~> 1.8)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.0)
slugize (0.0.3)
uglifier (2.7.2)
execjs (>= 0.3.0)
json (>= 1.8.0)
yajl-ruby (1.2.1)
PLATFORMS
ruby
DEPENDENCIES
algoliasearch (>= 1.6.1)
bundler (>= 1.7.9)
dotenv (>= 0.11.1)
googlestaticmap (>= 1.2.2)
htmlentities (>= 4.3.2)
jekyll (>= 3.0.3)
jekyll-paginate
newrelic_rpm (>= 3.9.8.273)
nokogiri (>= 1.6.3.1)
pygments.rb
rack (< 1.6.0)
rack-contrib (>= 1.2.0)
rack-host-redirect
rack-rewrite (>= 1.5.0)
rack-ssl-enforcer (>= 0.2.9)
rack-wwwhisper (>= 1.0)
rack-xframe-options (>= 0.1.2)
redcarpet
rspec (>= 3.1.0)
rubocop (>= 0.28.0)
rubyzip (>= 1.1.6)
simplecov (>= 0.9.1)
slugize (>= 0.0.3)
uglifier (>= 2.7.0)
RUBY VERSION
ruby 2.2.4p230
BUNDLED WITH
1.13.6

View File

@@ -1,184 +0,0 @@
# [developer.pebble.com][site]
[![Build Status](https://magnum.travis-ci.com/pebble/developer.getpebble.com.svg?token=HUQ9CCUxB447Nq1exrnd)][travis]
This is the repository for the [Pebble Developer website][site].
The website is built using [Jekyll](http://jekyllrb.com) with some plugins that
provide custom functionality.
For anyone who wants to contribute to the content of the site, you should find
the information in one of the sections below.
* [Blog Posts](#blog-posts)
* [Markdown](#markdown)
* [Landing Page Features](#landing-page-features)
* [Colors](#colors)
## Getting Started
Once you have cloned the project you will need to run `bundle install` to
install the Ruby dependencies. If you do not have [bundler](http://bundler.io/)
installed you will need to run `[sudo] gem install bundler` first.
You should also do `cp .env.sample .env` and edit the newly created `.env` file
with the appropriate values. Take a look at the
[Environment Variables documentation](/docs/environment.md) for more details.
To start the Jekyll web server, run `bundle exec jekyll serve`.
## JS Documentation
The PebbleKit JS and Rocky documentation is generated with the
[documentation.js](documentation.js.org) framework. The documentation tool can
create a JSON file from the JSDocs contained in the [js-docs](/js-docs)
folder.
To install documentation.js, run `npm install -g documentation`
To regenerate the `/source/_data/rocky-js.json` file, run `./scripts/generate-rocky-docs.sh`
> **NOTE**: This is intended to be a temporary hack. Ideally the rocky-js.json
> file is generated as part of the release generator (and built using the actual
> Rocky.js source, or stubs in the Tintin repository.
## Blog Posts
### Setting up a new author
Add your name to the `source/_data/authors.yml` so the blog knows who you are!
```
blogUsername:
name: First Last
photo: https://example.com/you.png
```
### Creating a new blog post
Add a Markdown file in `source/_posts/` with a filename in following the
format: `YYYY-MM-DD-Title-of-the-blog-most.md`.
Start the file with a block of YAML metadata:
```
---
title: Parlez-vous Pebble? Sprechen sie Pebble? ¿Hablas Pebble?
author: blogUsername
tags:
- Freshly Baked
---
```
You should pick one tag from this list:
* Freshly Baked - Posts announcing or talking about new features
* Beautiful Code - Posts about writing better code
* "#makeawesomehappen" - Hackathons/events/etc
* At the Pub - Guest Blog Posts (presumably written at a pub)
* Down the Rabbit Hole - How Pebble works 'on the inside'
* CloudPebble - Posts about CloudPebble
* Timeline - Posts about Timeline
### Setting the post's preview text
The blog's homepage will automatically generate a 'preview' of your blog post. It does this by finding the first set of 3 consecutive blank lines, and using everything before those lines as the preview.
You should aim to have your preview be 1-2 paragraphs, and end with a hook that causes the reader to want to click the 'Read More' link.
## Markdown
There is a [Markdown styleguide and additional syntax cheatsheat][markdown]
you should use if you are writing any Markdown for the site. That includes all
blog posts and guides.
## Landing Page Features
The landing page of the website contains a slideshow (powered by [slick][slick]).
The contents of the slideshow, or 'features' as we call them, are generated
from the features data file found at `source/_data/features.yaml`.
There are two main types of features, images and videos.
### Image Feature
```yaml
- title: Want to make your apps more internationally friendly?
url: /guides/publishing-tools/i18n-guide/
background_image: /images/landing-page/i18n-guide.png
button_text: Read our brand new guide to find out how
button_fg: black
button_bg: yellow
duration: 5000
```
It should be relatively clear what each of the fields is for. For the
`button_fg` and `button_bg` options, check out the [colors](#colors) section
for the available choices.
The `background_image` can either be a local asset file or an image on an
external web server.
**Please Remember:** The landing page will see a lot of traffic so you
should strive to keep image sizes small, while still maintaing relatively large
dimensions. Run the images through minifying tools, such as
[TinyPNG][tinypng] or [TinyJPG][tinyjpg], before commiting them to the site.
### Video Feature
```yaml
- title: Send a Smile with Android Actionable Notifications
url: /blog/2014/12/19/Leverage-Android-Actionable-Notifications/
background_image: /images/landing-page/actionable-notifications.png
video:
url: https://s3.amazonaws.com/developer.getpebble.com/videos/actionable-notifications.mp4
button_text: Learn how to supercharge Your Android Apps
button_fg: white
button_bg: green
duration: 5000
```
To prevent massively bloating the size of this repository, we are hosting all
videos externally on S3. If you do not have permission to upload videos to our
S3 bucket, you will need to ask someone who does!
In order to enable to videos to play across all of the browsers + platforms,
you will need to provided the video in MP4, OGV and WEBM formats.
There is a script provided in the scripts folder to do the automatic conversion
from MP4, and to export the first frame of the video as a PNG used as a
placeholder while the video loads.
```sh
./scripts/video-encode.sh PATH_TO_MP4
```
If you run the script as above, it will create an OGV, WEBM and PNG file in the same folder as the MP4. The PNG file should go in the `/assets/images/landing-page/` folder, and the three video files should be uploaded to S3.
## Colors
Buttons and Alerts come are available in several different color options, with
both foreground and background modifier classes to give you maximum control.
The available colors:
* white
* green
* blue
* red
* purple
* yellow
* orange
* lightblue
* dark-red
To set the background, use `--bg-<COLOR>` modifier. To set the foreground (i.e)
the text color, use `--fg-<COLOR>`.
## Troubleshooting
Trouble building the developer site? Read the [Troubleshooting](/docs/troubleshooting.md) page for some possible solutions.
[site]: https://developer.pebble.com
[markdown]: ./docs/markdown.md
[slick]: http://kenwheeler.github.io/slick/
[tinypng]: https://tinypng.com/
[tinyjpg]: https://tinyjpg.com/
[travis]: https://magnum.travis-ci.com/pebble/developer.getpebble.com

View File

@@ -1,28 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
task default: "assets:precompile"
namespace :assets do
desc "Precompile assets"
task :precompile do
Rake::Task["clean"].invoke
sh "bundle exec jekyll build --trace"
end
end
desc "Remove compiled files"
task :clean do
sh "rm -rf #{File.dirname(__FILE__)}/__public__/*"
end

View File

@@ -1,111 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
url: https://developer.pebble.com
https_url: https://developer.pebble.com
baseurl:
asset_path: /assets
external_server: https://developer-api.getpebble.com
title: Pebble Developers
description: The official developer website for the Pebble smartwatch.
source: source/
destination: __public__/
plugins_dir: plugins/
debug: true
gems: [jekyll-paginate]
# Blog Options
permalink: none
paginate: 8
paginate_path: "blog/:num"
excerpt_separator: "\n\n\n"
future: true
disqus:
short_name: pebbletechblog
show_comment_count: true
# Markdown Options
markdown: PebbleMarkdownParser
markdown_ext: md
# SASS options.
sass:
sass_dir: _sass
style: :compressed
# Helpful and easily changeable external links.
links:
pebble: https://www.pebble.com
jobs: https://www.pebble.com/jobs/
twitter: https://twitter.com/pebbledev/
cloudpebble: https://cloudpebble.net/
cloudpebble_beta: https://beta.cloudpebble.net/
devportal: https://dev-portal.getpebble.com/
site_repo: https://github.com/pebble/developer.getpebble.com/
community_resources_repo: https://github.com/pebble/community-resources/
github: https://github.com/pebble/
forums: https://forums.pebble.com
forums_developer: https://forums.pebble.com/c/development
pebblekit_android: https://github.com/pebble/pebble-android-sdk/
pebblekit_ios: https://github.com/pebble/pebble-ios-sdk/
examples_org: https://github.com/pebble-examples
pebblekit_android_jar: https://oss.sonatype.org/service/local/repositories/releases/content/com/getpebble/pebblekit/3.0.0/pebblekit-3.0.0-eclipse.jar
legal:
privacy: https://www.pebble.com/legal/privacy/
cookies: https://www.pebble.com/legal/cookies/
s3_assets: https://developer-assets.getpebble.com
pebble_tool_root: https://s3.amazonaws.com/assets.getpebble.com/pebble-tool/
libpebble: https://github.com/pebble/libpebble2
kickstarter3: https://www.kickstarter.com/projects/597507018/pebble-2-time-2-and-core-an-entirely-new-3g-ultra
discord_invite: http://discord.gg/aRUAYFN
# Jekyll collections.
collections:
guides:
output: true
permalink: /guides/:path/
changelogs:
output: true
permalink: /sdk/changelogs/:path/
# Default options based for various scopes
defaults:
- scope:
path: ""
type: "posts"
values:
layout: "blog/post"
generate_toc: true
permalink: /blog/:year/:month/:day/:title/
- scope:
path: ""
type: "guides"
values:
layout: guides/default
menu: true
generate_toc: true
guide_group:
guide_subgroup:
menu_section: guides
- scope:
path: ""
type: changelogs
values:
layout: sdk/changelog
generate_toc: true

View File

@@ -1,28 +0,0 @@
{
"name": "Pebble Developer Website",
"description": "The official Pebble Developer website.",
"website": "https://developer.pebble.com",
"repository": "https://github.com/pebble/developer.getpebble.com",
"env": {
"EXTERNAL_SERVER": {
"required": true
},
"DOCS_URL": {
"required": true
},
"ALGOLIA_APP_ID": {
"required": true
},
"ALGOLIA_API_KEY": {
"required": true
},
"ALGOLIA_SEARCH_KEY": {
"required": true
},
"ALGOLIA_PREFIX": "devsite-staging-",
"RACK_ENV": "staging",
"HEROKU_APP_NAME": {
"required": true
}
}
}

View File

@@ -1,53 +0,0 @@
require 'newrelic_rpm'
require 'rack/contrib/try_static'
require 'rack/rewrite'
require 'dotenv'
require 'rack/ssl-enforcer'
require 'rack/xframe-options'
require 'rack-host-redirect'
Dotenv.load
require 'dotenv'
def load_404
not_found_page = File.expand_path('../__public__/404.html', __FILE__)
File.read(not_found_page)
end
if ENV['RACK_ENV'] == 'development'
def not_found_html
load_404
end
else
use Rack::SslEnforcer,
:hsts => { :expires => 500, :subdomains => false },
:strict => true
not_found_html = load_404
end
use Rack::XFrameOptions, 'DENY'
# Determine if the C preview docs are enabled
docs_config = YAML.load_file('source/_data/docs.yaml')
preview_docs = docs_config.key?('c_preview')
use Rack::Rewrite do
# Redirect all old PebbleKit docs to their new location
r301 %r{/docs/js/(.*)}, '/docs/pebblekit-js/$1'
# Redirect C preview docs to main C docs if there are no preview docs
r302 %r{/docs/c/preview/?(.*)}, '/docs/c/$1' unless preview_docs
end
use Rack::HostRedirect, {
'developer.getpebble.com' => 'developer.pebble.com'
}
use Rack::TryStatic,
root: '__public__',
urls: %w(/),
try: %w(.html index.html /index.html)
run lambda{ |_env|
[404, { 'Content-Type' => 'text/html' }, [not_found_html]]
}

File diff suppressed because one or more lines are too long

View File

@@ -1,12 +0,0 @@
# Pebble Developer Site &middot; Development Guide
## Handlebars Templates
In order to reduce the size of the JS of the site, we are now pre-compiling
the Handlebars templates and just using the runtime Handlebars library.
If you change, add or remove from the templates, you just recompile them
into the file at `/source/assets/js/templates.js`.
There is a bash script at `/scripts/update-templates.sh` that you can use to
generate this file.

View File

@@ -1,84 +0,0 @@
# Environment Variables
The following environment variables are used in the generation of the site.
## URL
This overrides the `url` configuration parameter of Jeyll. Set this to the root
of where the site will be hosted.
```
URL=http://developer.pebble.com
```
## HTTPS_URL
This overrides the `https_url` configuration parameter of Jeyll. Set this to
the secure root of where the site will be hosted.
```
HTTPS_URL=https://developer.pebble.com
```
## PORT
The port on which the Jekyll server will listen. If you don't set this it will
default to port `4000`.
```
PORT=8000
```
## ASSET_PATH
This sets the `asset_path` configuration variable, which tells the site where
the assets are to be found.
During development and testing, this can be set to the relative URL of the
assets folder inside the main site.
For production, this should be set to the CDN where the assets will be uploaded.
*Note:* As of 8th January 2014, the production version of the site still used
local assets and not a CDN.
```
ASSET_PATH=assets/
```
## EXTERNAL_SERVER
This sets the `external_server` configuration variable, which tells the site the
location of the external server used for events, community blog and contact.
```
EXTERNAL_SERVER=https://developer-api.getpebble.com
```
## DOCS_URL
The URL of the server on which the documentation sources are being built.
The production and staging values are private, so if you do not work for Pebble
you will have to omit it from the environment (or `.env` file). Sorry
## ALGOLIA_*
The site search is powered by [Algolia](https://algolia.com). There are four
environment variables that are required to turn on indexing at build time and
also correctly setup the client JS for searching. The production and staging
values can be found on our Algolia account.
If you do not work for Pebble, or don't care about testing the indexing, then
omit these values from the environment (or `.env` file) to disable Algolia.
The `ALGOLIA_PREFIX` value is extremely important. Make sure you set it if you
are enabling Algolia support on the site, and check that it matches the scoped
search key.
```
ALGOLIA_APP_ID=
ALGOLIA_API_KEY=
ALGOLIA_SEARCH_KEY=
ALGOLIA_PREFIX=
```

View File

@@ -1,305 +0,0 @@
# Writing Markdown
If you are writing anything in Markdown for the Pebble Developer site, you
should read this guide to learn about some of the rules and enhancements that
the site has, beyond those of "standard Markdown".
## Styleguide
### 80 character lines
To keep your Markdown files readable and easy to review, please break all lines
at 80 characters.
*NOTE:* The line breaking does not affect the HTML output, this is purely to
keep the source files readable and reviewable.
### Headers
Use the `#`, `##` etc syntax for headers, and include a space after the hashes
and before the header text.
```
## Write Headers Like This
##Don't Write Them Like This
And Definitely Don't Do This
=======
```
You should also generally avoid using the top level header (`#`) because the
page that is displaying the content will be using the document title in a \<h1\>
tag automatically.
#### Table of Contents
If enabled, the table of contents for the document will include all headers on
the page.
You can enable/disable table of contents generation for a specific page in the
YAML metadata:
```
generate_toc: true
```
#### Anchors
All headers automatically have anchors attached to them, so you can easily link
to sections of the page. The ID for the header will be the slugized header text.
For example, `## Install Your App` will become `#install-your-app`.
### Blockcode
Use triple backticks for block code, and
[specify the language](http://pygments.org/languages/) to ensure the syntax is
highlighted correctly.
```js
var foo = 'bar';
```
#### Click to Copy
By default, all code blocks will include the Click to Copy button in the
top right corner. If you want to disable it, prepend the language with `nc^`.
```nc^text
This is not for copying!
```
### Images
In blog posts and guides, images will be block elements that are centered on
the page. *Plan accordingly.*
#### Size
You can control the width (and optionally height) of images using the following
syntax:
```
![Image with width](/images/huge_image.png =300)
![Image with width and height](/images/huge_image.png =300x400)
```
### HTML
Do not use HTML unless you **absolutely** have to. It is almost always better to
use Markdown so that we can more easily maintain a consistent style across the
site.
## Additional Syntax
### Buttons
To convert any link into a button simply append a `>` onto the end of the text.
```
[Button Text >](http://google.com/)
```
You can optionally pass extra button classes after the `>` to modify the style
of the button.
```
[Wide Orange Button >{wide,fg-orange}](http://google.com)
```
The available classes are:
* wide
* small
* center
* fg-COLOR
* bg-COLOR
*Where COLOR is any one of the [available colors](README.md#colors).*
### Link Data
To add additional data attributes to links (useful for outbound tracking),
append a `>` to the end of the link title, and format the content as below.
```
[Link Text](http://google.com "Link Title >{track-event:click,track-name:google}")
```
This will create a link with the attributes `data-track-event="click"` and
`data-track-name="google"`.
### SDK Documentation Links
If you wish to link to a section of the SDK documentation, you can do so using
double backticks. This can either be done to enhance existing inline code
or in the text of a link.
```
This will link to the ``window_create`` documentation.
You should check out the page on [Events](``event services``)
```
### Pebble Screenshots
If you want to provide a watch screenshot and have it displayed in a Pebble
wrapper, you should upload the 144x168 image and use the following syntax.
```
![ >{pebble-screenshot,pebble-screenshot--time-red}](/images/screenshot.png)
```
You can pick from any of the following screenshot wrappers:
* pebble-screenshot--black
* pebble-screenshot--white
* pebble-screenshot--red
* pebble-screenshot--gray
* pebble-screenshot--orange
* pebble-screenshot--steel-black
* pebble-screenshot--steel-stainless
* pebble-screenshot--snowy-black
* pebble-screenshot--snowy-red
* pebble-screenshot--snowy-white
* pebble-screenshot--time-round-black-20
* pebble-screenshot--time-round-red-14
The following screenshot classes exist, but the accompanying images are not
currently available. They will be aliased to black-20 or red-14 as size
dictates:
* pebble-screenshot--time-round-rosegold-14
* pebble-screenshot--time-round-silver-14
* pebble-screenshot--time-round-silver-20
> Please match the wrapper to the screenshot where possible. For example, do not
use an original Pebble wrapper with a color screenshot.
#### Screenshot Viewer
If you want to show matching screenshots across multiple platforms, you should use the new
`screenshot_viewer` tag.
Here is an example of it in use:
```
{% screenshot_viewer %}
{
"image": "/images/guides/pebble-apps/display-animations/submenu.png",
"platforms": [
{ "hw": "basalt", "wrapper": "time-red" },
{ "hw": "chalk", "wrapper": "time-round-red-14" }
]
}
{% endscreenshot_viewer %}
```
The URL to the image gets the hardware platform insert into it, so in order to make
the above example work, you should have two files with the following names:
```
/source/assets/images/guides/pebble-apps/display-animations/submenu~basalt.png
/source/assets/images/guides/pebble-apps/display-animations/submenu~chalk.png
```
### Alerts
Some information requires more prominent formatting than standard block notes.
Use the `alert` Liquid tag for this purpose. Both 'notice' (purple) and
'important' (dark red) are supported for appropriate levels of highlighting.
Some examples are below:
```
{% alert important %}
PebbleKit JS and PebbleKit Android/iOS may **not** be used in conjunction.
{% endalert %}
```
```
{% alert notice %}
This API is currently in the beta stage, and may be changed before final
release.
{% endalert %}
```
### SDK Platform Specific Paragraphs
On pages that have the SDK Platform choice system, you can tag paragraphs as
being only relevant for CloudPebble or local SDK users. Text, code snippets,
images, and other markdown are all supported.
First, add `platform_choice: true` to the page YAML metadata.
Specify platform-specific sections of markdown using the `platform` Liquid tag:
```
{% platform local %}
Add the resource to your project in `package.json`.
{% endplatform %}
{% platform cloudpebble %}
Add the resource to your project by clicking 'Add New' next to 'Resources' in
the project sidebar.
{% endplatform %}
```
### Formatting
The following additional text formatting syntax is supported.
#### Strikethrough
```
This is some ~~terribly bad~~ amazingly good code.
```
#### Highlight
```
CloudPebble is ==extremely== good.
```
#### Tables
Tables are supported with the
[PHP Markdown syntax](https://michelf.ca/projects/php-markdown/extra/#table).
```
| First Header | Second Header |
| ------------- | ------------- |
| Content Cell | Content Cell |
| Content Cell | Content Cell |
```
### Emoji
You can use emoji in your text by using the colon syntax.
```
If you're a beginner Pebble developer, you should use :cloud:Pebble
```
### Embedded Content
#### YouTube
To embed a YouTube video or playlist, use the standard link syntax with EMBED
as the link title.
```
You should check out this video on developing Pebble apps:
[EMBED](https://www.youtube.com/watch?v=LU_hPBhgjGQ)
```
#### Gist
To embed a GitHub Gist, use the standard link syntax with EMBED as the link
title.
```
Here is the Gist code.
[EMBED](https://gist.github.com/JaviSoto/5405969)
```

View File

@@ -1,16 +0,0 @@
# Troubleshooting
This page contains fixes to known problems encountered from building the
developer site, and how they were fixed. This may help you if you have
the same problems.
## Nokogiri
**Error**
> An error occurred while installing nokogiri (1.6.7.2), and Bundler cannot continue.
> Make sure that `gem install nokogiri -v '1.6.7.2'` succeeds before bundling.
**Solution**
`gem install nokogiri -- --use-system-libraries`

View File

@@ -1,428 +0,0 @@
/**
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @namespace Pebble
*
* @desc The Pebble namespace is where all of the Pebble specific methods and
* properties exist. This class contains methods belonging to PebbleKit JS and
* allows bi-directional communication with a C or JavaScript watchapp, as well as managing
* the user's timeline subscriptions, creating AppGlance slices and obtaining
* information about the currently connected watch.
*/
var Pebble = new Object;
/**
* @desc Adds a listener for PebbleKit JS events, such as when an ``AppMessage`` is
* received or the configuration view is opened or closed.
*
* #### Event Type Options
*
* Possible values:
*
* * `ready` - The watchapp has been launched and the PebbleKit JS component
* is now ready to receive events.
* * `appmessage` - The watch sent an ``AppMessage`` to PebbleKit JS. The
* AppMessage ``Dictionary`` is contained in the payload property (i.e:
* `event.payload`). The payload consists of key-value pairs, where the keys
* are strings containing integers (e.g: "0"), or aliases for keys defined
* in package.json (e.g: "KEY_EXAMPLE"). Values should be integers, strings
* or byte arrays (arrays of characters). This event is not available to
* {@link /docs/rockyjs/ Rocky.js} applications, and attempting to register it will throw an exception.
* * `showConfiguration` - The user has requested the app's configuration
* webview to be displayed. This can occur either upon the app's initial
* install or when the user taps 'Settings' in the 'My Pebble' view within
* the phone app.
* * `webviewclosed` - The configuration webview was closed by the user. If
* the webview had a response, it will be contained in the response property
* (i.e: `event.response`). This response can be used to feed back user
* preferences to the watchapp.
* * `message` - Provide a {@link #PostMessageCallback PostMessageCallback}
* as the callback. The message event is emitted every time PebbleKit JS
* receives a {@link #postMessage postMessage} from the {@link /docs/rockyjs/ Rocky.js}
* application. The payload contains a simple JavaScript object. (i.e. `event.data`).
* This event type can only be used with {@link /docs/rockyjs/ Rocky.js} applications.
* * `postmessageconnected` - Provide a {@link #PostMessageConnectedCallback PostMessageConnectedCallback}
* as the callback. The event may be emitted immediately upon subscription,
* if the subsystem is already connected. It is also emitted when connectivity is established.
* This event type can only be used with {@link /docs/rockyjs/ Rocky.js} applications.
* * `postmessagedisconnected` - Provide a {@link #PostMessageDisconnectedCallback PostMessageDisconnectedCallback}
* as the callback. The event may be emitted immediately upon subscription,
* if the subsystem is already disconnected. It is also emitted when connectivity is lost.
* This event type can only be used with {@link /docs/rockyjs/ Rocky.js} applications.
* * `postmessageerror` - Provide a {@link #PostMessageErrorCallback PostMessageErrorCallback}
* as the callback. The event is emitted when a transmission error occurrs.
* Your message has not been delivered. The type of error is not provided.
* This event type can only be used with {@link /docs/rockyjs/ Rocky.js} applications.
*
* @param {String} type - The type of the event, from the list described above.
* @param {EventCallback} callback - The developer defined {@link #EventCallback EventCallback}
* to receive any events of the type specified that occur.
*/
Pebble.addEventListener = function(type, callback) { };
/**
* @desc Attaches an event handler to the specified events. Synonymous with
[Pebble.addEventListener()](#addEventListener). Only applicable to
{@link /docs/rockyjs/ Rocky.js} applications.
*
* `Pebble.on(type, callback);`
*
* @param {String} type - The type of the event, from the list described above.
* @param {EventCallback} callback - The developer defined {@link #EventCallback EventCallback}
* to receive any events of the type specified that occur.
*/
Pebble.on = function(type, callback) { };
/**
* @desc Remove an existing event listener previously registered with
* [Pebble.addEventListener()](#addEventListener) or [Pebble.on()](#on).
*
* @param {String} type - The type of the event listener to be removed. See
* [Pebble.addEventListener()](#addEventListener) for a list of available event types.
* @param {Function} callback - The existing developer-defined function that was
* previously registered.
*/
Pebble.removeEventListener = function(type, callback) { };
/**
* @desc Remove an existing event handler from the specified events. Synonymous
* with [Pebble.removeEventListener()](#removeEventListener). Only applicable to
* {@link /docs/rockyjs/ Rocky.js} applications.
*
* `Pebble.off(type, callback);`
*
* @param {String} type - The type of the event listener to be removed. See
* [Pebble.addEventListener()](#addEventListener) for a list of available types.
* @param {Function} callback - The existing developer-defined function that was
* previously registered.
*/
Pebble.off = function(type, callback) { };
/**
* @desc Show a simple modal notification on the connected watch.
*
* @param {String} title - The title of the notification
* @param {String} body - The main content of the notification
*/
Pebble.showSimpleNotificationOnPebble = function(title, body) { };
/**
* @desc Send an AppMessage to the app running on the watch. Messages should be
* in the form of JSON objects containing key-value pairs. See
* Pebble.sendAppMessage() for valid key and value data types.
* `Pebble.sendAppMessage = function(data, onSuccess, onFailure) { };`
* Please note that `sendAppMessage` is `undefined` in
* {@link /docs/rockyjs/ Rocky.js} applications, see {@link #postMessage postMessage} instead.
*
* @returns {Number} The transaction id for this message
*
* @param {Object} data - A JSON object containing key-value pairs to send to
* the watch. Values in arrays that are greater then 255 will be mod 255
* before sending.
* @param {AppMessageAckCallback} onSuccess - A developer-defined {@link #AppMessageAckCallback AppMessageAckCallback}
* callback to run if the watch acknowledges (ACK) this message.
* @param {AppMessageOnFailure} onFailure - A developer-defined {@link #AppMessageNackCallback AppMessageNackCallback}
* callback to run if the watch does NOT acknowledge (NACK) this message.
*/
Pebble.sendAppMessage = function(data, onSuccess, onFailure) { };
/**
* @desc Sends a message to the {@link /docs/rockyjs/ Rocky.js} component. Please be aware
* that messages should be kept concise. Each message is queued, so
* `postMessage()` can be called multiple times immediately. If there is a momentary loss of connectivity, queued
* messages may still be delivered, or automatically removed from the queue
* after a few seconds of failed connectivity. Any transmission failures, or
* out of memory errors will be raised via the `postmessageerror` event.
*
* `Pebble.postMessage({temperature: 30, conditions: 'Sunny'});`
*
* @param {Object} data - A {@link #PostMessageCallback PostMessageCallback} containing
* the data to deliver to the watch.
* This will be received in the `data` field of the `type` delivered to
* the `on('message', ...)` handler.
*/
Pebble.postMessage = function(data) { };
/**
* @desc Get the user's timeline token for this app. This is a string and is
* unique per user per app. Note: In order for timeline tokens to be
* available, the app must be submitted to the Pebble appstore, but does not
* need to be public. Read more in the
* {@link /guides/pebble-timeline/timeline-js/ timeline guides}.
*
* @param {TimelineTokenCallback} onSuccess - A developer-defined {@link #TimelineTokenCallback TimelineTokenCallback}
* callback to handle a successful attempt to get the timeline token.
* @param {Function} onFailure - A developer-defined callback to handle a
* failed attempt to get the timeline token.
*/
Pebble.getTimelineToken = function(onSuccess, onFailure) { };
/**
* @desc Subscribe the user to a timeline topic for your app. This can be used
* to filter the different pins a user could receive according to their
* preferences, as well as maintain groups of users.
*
* @param {String} topic - The desired topic to be subscribed to. Users will
* receive all pins pushed to this topic.
* @param {Function} onSuccess - A developer-defined callback to handle a
* successful subscription attempt.
* @param {Function} onFailure - A developer-defined callback to handle a
* failed subscription attempt.
*/
Pebble.timelineSubscribe = function(topic, onSuccess, onFailure) { };
/**
* @desc Unsubscribe the user from a timeline topic for your app. Once
* unsubscribed, the user will no longer receive any pins pushed to this
* topic.
*
* @param {String} topic - The desired topic to be unsubscribed from.
* @param {Function} onSuccess - A developer-defined callback to handle a
* successful unsubscription attempt.
* @param {Function} onFailure - A developer-defined callback to handle a
* failed unsubscription attempt.
*/
Pebble.timelineUnsubscribe = function(topic, onSuccess, onFailure) { };
/**
* @desc Obtain a list of topics that the user is currently subscribed to. The
* length of the list should be checked to determine whether the user is
* subscribed to at least one topic.
*
* `Pebble.timelineSubscriptions(function(topics) { console.log(topics); }, function() { console.log('error'); } );`
*
* @param {TimelineTopicsCallback} onSuccess - The developer-defined function to process the
* retuned list of topic strings.
* @param {Function} onFailure - The developer-defined function to gracefully
* handle any errors in obtaining the user's subscriptions.
*/
Pebble.timelineSubscriptions = function(onSuccess, onFailure) { };
/**
* @desc Obtain an object containing information on the currently connected
* Pebble smartwatch.
*
* **Note:** This function is only available when using the Pebble Time
* smartphone app. Check out our guide on {@link /guides/communication/using-pebblekit-js Getting Watch Information}
* for details on how to use this function.
*
* @returns {WatchInfo} A {@link #WatchInfo WatchInfo} object detailing the
* currently connected Pebble watch.
*/
Pebble.getActiveWatchInfo = function() { };
/**
* @desc Returns a unique account token that is associated with the Pebble
* account of the current user.
*
* **Note:** The behavior of this changed slightly in SDK 3.0. Read the
* {@link /guides/migration/migration-guide-3/ Migration Guide} to learn the
* details and how to adapt older tokens.
*
* @returns {String} A string that is guaranteed to be identical across devices
* if the user owns several Pebble or several mobile devices. From the
* developer's perspective, the account token of a user is identical across
* platforms and across all the developer's watchapps. If the user is not
* logged in, this function will return an empty string ('').
*/
Pebble.getAccountToken = function() { };
/**
* @desc Returns a a unique token that can be used to identify a Pebble device.
*
* @returns {String} A string that is is guaranteed to be identical for each
* Pebble device for the same app across different mobile devices. The token
* is unique to your app and cannot be used to track Pebble devices across
* applications.
*/
Pebble.getWatchToken = function() { };
/**
* @desc Triggers a reload of the app glance which first clears any existing
* slices and then adds the provided slices.
*
* @param {AppGlanceSlice} appGlanceSlices - {@link #AppGlanceSlice AppGlanceSlice}
* JSON objects to add to the app glance.
* @param {AppGlanceReloadSuccessCallback} onSuccess - The developer-defined
* callback which is called if the reload operation succeeds.
* @param {AppGlanceReloadFailureCallback} onFailure - The developer-defined
* callback which is called if the reload operation fails.
*/
Pebble.appGlanceReload = function(appGlanceSlices, onSuccess, onFailure) { };
/**
* @desc When an app is marked as configurable, the PebbleKit JS component must
* implement `Pebble.openURL()` in the `showConfiguration` event handler. The
* Pebble mobile app will launch the supplied URL to allow the user to configure
* the watchapp or watchface. See the
* {@link /guides/user-interfaces/app-configuration-static/ App Configuration guide}.
*
* @param {String} url - The URL of the static configuration page.
*/
Pebble.openURL = function(url) { };
/**
* @typedef {Function} AppGlanceReloadSuccessCallback
* @memberof Pebble
*
* @desc Called when AppGlanceReload is successful.
* @param {AppGlanceSlice} AppGlanceSlices - An {@link #AppGlanceSlice AppGlanceSlice} object
* containing the app glance slices.
*/
/**
* @typedef {Function} AppGlanceReloadFailureCallback
* @memberof Pebble
*
* @desc Called when AppGlanceReload has failed.
* @param {AppGlanceSlice} AppGlanceSlices - An {@link #AppGlanceSlice AppGlanceSlice} object
* containing the app glance slices.
*/
/**
* @typedef {Function} AppMessageAckCallback
* @memberof Pebble
*
* @desc Called when an AppMessage is acknowledged by the watch.
* @param {Object} data - An object containing the callback data. This contains
* the `transactionId` which is the transaction ID of the message.
*/
/**
* @typedef {Function} AppMessageNackCallback
* @memberof Pebble
*
* @desc Called when an AppMessage is not acknowledged by the watch.
* @param {Object} data - An object containing the callback data. This contains
* the `transactionId` which is the transaction ID of the message
* @param {String} error - The error message
*/
/**
* @typedef {Function} EventCallback
* @memberof Pebble
*
* @desc Called when an event of any type previously registered occurs. The
* parameters are different depending on the type of event, shown in
* brackets for each parameter listed here.
* @param {Object} event - An object containing the event information, including:
* * `type` - The type of event fired, from the list in the description of [Pebble.addEventListener()](#addEventListener).
* * `payload` - The dictionary sent over ``AppMessage`` consisting of
* key-value pairs. *This field only exists for `appmessage` events.*
* * `response` - The contents of the URL navigated to when the
* configuration page was closed, after the anchor. This may be encoded,
* which will require use of decodeURIComponent() before reading as an
* object. *This field only exists for for `webviewclosed` events.*
*/
/**
* @typedef {Function} TimelineTokenCallback
* @memberof Pebble
*
* @desc Called when the user's timeline token is available.
* @param {String} token - The user's token.
*/
/**
* @typedef {Function} TimelineTopicsCallback
* @memberof Pebble
*
* @desc Called when the user's list of subscriptions is available for processing by the developer.
* @param {[String]} List of topic strings that the user is subscribed to
*/
/**
* @typedef {Function} PostMessageCallback
* @memberof Pebble
*
* @desc The callback function signature to be used with the `message`
* {@link #on event}.
*
* @param {Object} event - An object containing information about the event:
* * `type` - The type of event which was triggered.
* * `data` - The data sent within the message.
*/
/**
* @typedef {Function} PostMessageErrorCallback
* @memberof Pebble
*
* @desc The callback function signature to be used with the `postmessageerror`
* {@link #on event}.
*
* @param {Object} event - An object containing information about the event:
* * `type` - The type of event which was triggered.
* * `data` - The data failed to send within the message.
*/
/**
* @typedef {Function} PostMessageConnectedCallback
* @memberof Pebble
*
* @desc The callback function signature to be used with the `postmessageconnected`
* {@link #on event}.
*
* @param {Object} event - An object containing information about the event:
* * `type` - The type of event which was triggered.
*/
/**
* @typedef {Function} PostMessageDisconnectedCallback
* @memberof Pebble
*
* @desc The callback function signature to be used with the `postmessagedisconnected`
* {@link #on event}.
*
* @param {Object} event - An object containing information about the event:
* * `type` - The type of event which was triggered.
*/
/**
* @typedef {Object} WatchInfo
* @memberof Pebble
*
* @desc Provides information about the connected Pebble smartwatch.
*
* @property {String} platform - The hardware platform, such as `basalt` or `emery`.
* @property {String} model - The watch model, such as `pebble_black`
* @property {String} language - The user's currently selected language on
* this watch.
* @property {Object} firmware - An object containing information about the
* watch's firmware version, including:
* * `major` - The major version
* * `minor` - The minor version
* * `patch` - The patch version
* * `suffix` - Any additional version information, such as `beta3`
*/
/**
* @typedef {Object} AppGlanceSlice
* @memberof Pebble
*
* @desc The structure of an app glance.
*
* @property {String} expirationTime - Optional ISO date-time string of when
the entry should expire and no longer be shown in the app glance.
* @property {Object} layout - An object containing:
* * `icon` - URI string of the icon to display in the app glance, e.g. system://images/ALARM_CLOCK.
* * `subtitleTemplateString` - Template string that will be displayed in the subtitle of the app glance.
*/

View File

@@ -1,377 +0,0 @@
/**
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @namespace CanvasRenderingContext2D
* @desc The CanvasRenderingContext2D interface is used for drawing
* rectangles, text, images and other objects onto the canvas element. It
* provides the 2D rendering context for the drawing on the device's display.
*
* The canvas uses a standard x and y
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes coordinate system}.
*
* The `CanvasRenderingContext2D` object is obtained as a parameter in the
* {@link /docs/rockyjs/rocky#on rocky.on('draw', ...)} event.
*
* `rocky.on('draw', function(drawEvent) {<br>&nbsp;&nbsp;var ctx = drawEvent.context;<br>});`
*
* The state of pixels is maintained between each draw, so developers are
* responsible for clearing an area, before drawing again.
*
* Please note that this API is still in development and there may be some
* limitations, which are documented below. We will also be adding support
* for more common APIs in future releases.
*/
var CanvasRenderingContext2D = {
/**
* @typedef {Object} TextMetrics
* @desc The TextMetrics interface represents the dimensions of a text
* in the canvas (display), as created by {@link #measureText measureText}.
*
* @property {Number} width - Calculated width of text in pixels.
* @property {Number} height - Calculated height of text in pixels.
*/
/**
* @typedef {Object} Canvas
* @desc Provides information about the device's canvas (display). This is not
* actually a DOM element, it is provided for standards compliance only.
*
* `rocky.on('draw', function(drawEvent) {<br>&nbsp;&nbsp;var ctx = drawEvent.context;<br>&nbsp;&nbsp;var h = ctx.canvas.unobstructedHeight;<br>});`
*
* @property {Number} clientWidth - The full width of the canvas.
* @property {Number} clientHeight - The full height of the canvas.
* @property {Number} unobstructedWidth - The width of the canvas that is not
* obstructed by system overlays (Timeline Quick View).
* @property {Number} unobstructedHeight - The height of the canvas that is
* not obstructed by system overlays (Timeline Quick View).
*/
/**
* @desc Specifies the color to use inside shapes. The default is
* `#000` (black).
*
* #### Options
*
* Possible values:
*
* * Most (but not all) CSS color names. e.g. `blanchedalmond`
* * Pebble color names. e.g. `shockingpink`
* * Hex color codes, short and long. e.g. `#FFFFFF` or `#FFF`
*
* Please note that we currently only support solid colors. You may specifiy
* `transparent` or `clear` for transparency, but we do do not support
* partial transparency or the `#RRGGBBAA` notation yet.
*
* `ctx.fillStyle = 'white';`
*
*/
fillStyle,
/**
* @desc Specifies the color to use for lines around shapes. The
* default is `#000` (black).
*
* #### Options
*
* Possible values:
*
* * Most (but not all) CSS color names. e.g. `blanchedalmond`
* * Pebble color names. e.g. `shockingpink`
* * Hex color codes, short and long. e.g. `#FFFFFF` or `#FFF`
*
* Please note that we currently only support solid colors. You may specifiy
* `transparent` or `clear` for transparency, but we do do not support
* partial transparency or the `#RRGGBBAA` notation yet.
*
* `ctx.strokeStyle = 'red';`
*
*/
strokeStyle,
/**
* @desc A {@link #Canvas Canvas} object containing information about
* the system's canvas (display).
*/
canvas,
/**
* @desc The width of lines drawn (to the nearest integer) with the
* context (`1.0` by default).
*
* `ctx.lineWidth = 8;`
*
*/
lineWidth,
/**
* @desc Specifies the current text style being used when drawing text.
* Although this string uses the same syntax as a CSS font specifier, you
* cannot specifiy arbitrary values and you must only use one of the values below.
*
* The default font is `14px bold Gothic`.
*
* `ctx.font = '28px bold Droid-serif';`
*
* #### Options
*
* Possible values:
*
* * `18px bold Gothic`
* * `14px Gothic`
* * `14px bold Gothic`
* * `18px Gothic`
* * `24px Gothic`
* * `24px bold Gothic`
* * `28px Gothic`
* * `28px bold Gothic`
* * `30px bolder Bitham`
* * `42px bold Bitham`
* * `42px light Bitham`
* * `42px Bitham-numeric`
* * `34px Bitham-numeric`
* * `21px Roboto`
* * `49px Roboto-subset`
* * `28px bold Droid-serif`
* * `20px bold Leco-numbers`
* * `26px bold Leco-numbers-am-pm`
* * `32px bold numbers Leco-numbers`
* * `36px bold numbers Leco-numbers`
* * `38px bold numbers Leco-numbers`
* * `42px bold numbers Leco-numbers`
* * `28px light numbers Leco-numbers`
*/
font,
/**
* @desc Specifies the current text alignment being used when drawing
* text. Beware that the alignment is based on the x-axis coordinate value of
* the {@link #fillText CanvasRenderingContext2D.fillText} method.
*
* `ctx.textAlign = 'center';`
*
* #### Options
*
* Possible values:
*
* * `left` - The text is left-aligned
* * `right` - The text is right-aligned
* * `center` - The text is center-aligned
* * `start` (default) - The text is aligned left, unless using a
* right-to-left language. Currently only left-to-right is supported.
* * `end` - The text is aligned right, unless using a right-to-left
* language. Currently only left-to-right is supported.
*/
textAlign
};
/**
* @desc Sets all pixels in the rectangle at (`x`,`y`) with size
* (`width`, `height`) to black, erasing any previously drawn content.
*
* `ctx.clearRect(0, 0, 144, 168);`
*
* @param {Number} x - The x-axis coordinate of the rectangle's starting point
* @param {Number} y - The y-axis coordinate of the rectangle's starting point
* @param {Number} width - The rectangle's width
* @param {Number} height - The rectangle's height
*/
CanvasRenderingContext2D.clearRect = function(x, y, width, height) { };
/**
* @desc Draws a filled rectangle at (`x`,`y`) with size (`width`, `height`),
* using the current fill style.
*
* `ctx.fillRect(0, 30, 144, 30);`
*
* @param {Number} x - The x-axis coordinate of the rectangle's starting point
* @param {Number} y - The y-axis coordinate of the rectangle's starting point
* @param {Number} width - The rectangle's width
* @param {Number} height - The rectangle's height
*/
CanvasRenderingContext2D.fillRect = function(x, y, width, height) { };
/**
* @desc Paints a rectangle at (`x`,`y`) with size (`width`, `height`),
* using the current stroke style.
*
* `ctx.strokeRect(0, 30, 144, 30);`
*
* @param {Number} x - The x-axis coordinate of the rectangle's starting point
* @param {Number} y - The y-axis coordinate of the rectangle's starting point
* @param {Number} width - The rectangle's width
* @param {Number} height - The rectangle's height
*/
CanvasRenderingContext2D.strokeRect = function(x, y, width, height) { };
/**
* @desc Draws (fills) `text` at the given (`x`,`y`) position.
*
* `ctx.fillText('Hello World', 0, 30, 144);`
*
* @param {String} text - The text to draw
* @param {Number} x - The x-axis coordinate of the text's starting point
* @param {Number} y - The y-axis coordinate of the text's starting point
* @param {Number} maxWidth - (Optional) Maximum width to draw. If specified,
* and the string is wider than the width, the font is adjusted to use a
* smaller font.
*/
CanvasRenderingContext2D.fillText = function(text, x, y, maxWidth) { };
/**
* @desc Returns a {@link #TextMetrics TextMetrics} object containing
* information about `text`.
*
* `var dimensions = ctx.measureText('Hello World');`
*
* @returns {TextMetrics} - A ``TextMetrics`` object with information about
* the measured text
*
* @param {String} text - The text to measure
*/
CanvasRenderingContext2D.measureText = function(text) { };
/**
* @desc Starts a new path by emptying the list of sub-paths. Call this
* method when you want to create a new path.
*
* `ctx.beginPath();`
*/
CanvasRenderingContext2D.beginPath = function() { };
/**
* @desc Causes the point of the pen to move back to the start of the
* current sub-path. It tries to add a straight line (but does not
* actually draw it) from the current point to the start. If the shape has
* already been closed or has only one point, this function does nothing.
*
* `ctx.closePath();`
*/
CanvasRenderingContext2D.closePath = function() { };
/**
* @desc Moves the starting point of a new sub-path to the (`x`,`y`)
* coordinates.
*
* `ctx.moveTo(10, 20);`
*
* @param {Number} x - The destination point on the x-axis
* @param {Number} y - The destination point on the y-axis
*/
CanvasRenderingContext2D.moveTo = function(x, y) { };
/**
* @desc Connects the last point of the sub-path to the (`x`,`y`)
* coordinates with a straight line.
*
* `ctx.lineTo(10, 20);`
*
* @param {Number} x - The destination point on the x-axis
* @param {Number} y - The destination point on the y-axis
*/
CanvasRenderingContext2D.lineTo = function(x, y) { };
/**
* @desc Adds an arc to the path which is centered at (`x`,`y`)
* position with radius `r` starting at `startAngle` and ending at
* `endAngle` going in the direction determined by the `anticlockwise`
* parameter (defaulting to clockwise).
*
* If `startAngle` > `endAngle` nothing will be drawn, and if the difference
* between `startAngle` and `endAngle` exceeds 2π, a full circle will be drawn.
*
* `// Draw a full circle outline<br>ctx.strokeStyle = 'white';<br>ctx.beginPath();<br>ctx.arc(72, 84, 40, 0, 2 * Math.PI, false);<br>ctx.stroke();`
*
* Please note this function does not work with `.fill`, you must use
* {@link #rockyFillRadial CanvasRenderingContext2D.rockyFillRadial} instead.
*
* @param {Number} x - The x-axis coordinate of the arc's center
* @param {Number} y - The y-axis coordinate of the arc's center
* @param {Number} r - The radius of the arc
* @param {Number} startAngle - The angle at which the arc starts, measured
* clockwise from the positive x axis and expressed in radians.
* @param {Number} endAngle - The angle at which the arc ends, measured
* clockwise from the positive x axis and expressed in radians.
* @param {Bool} [anticlockwise] - (Optional) `Boolean` which, if `true`,
* causes the arc to be drawn counter-clockwise between the two angles
* (`false` by default)
*/
CanvasRenderingContext2D.arc = function(x, y, r, startAngle, endAngle, anticlockwise) { };
/**
* @desc Creates a path for a rectangle at position (`x`,`y`) with a
* size that is determined by `width` and `height`. Those four points are
* connected by straight lines and the sub-path is marked as closed, so
* that you can fill or stroke this rectangle.
*
* `ctx.rect(0, 30, 144, 50);`
*
* @param {Number} x - The x-axis coordinate of the rectangle's starting point
* @param {Number} y - The y-axis coordinate of the rectangle's starting point
* @param {Number} width - The rectangle's width
* @param {Number} height - The rectangle's height
*/
CanvasRenderingContext2D.rect = function(x, y, width, height) { };
/**
* @desc Fills the current path with the current {@link #fillStyle fillStyle}.
*
* `ctx.fill();`
*/
CanvasRenderingContext2D.fill = function() { };
/**
* @desc Strokes the current path with the current {@link #strokeStyle strokeStyle}.
*
* `ctx.stroke();`
*/
CanvasRenderingContext2D.stroke = function() { };
/**
* @desc Saves the entire state of the canvas by pushing the current
* state onto a stack.
*
* `ctx.save();`
*/
CanvasRenderingContext2D.save = function() { };
/**
* @desc Restores the most recently saved canvas state by popping the
* top entry in the drawing state stack. If there is no saved state, this
* method does nothing.
*
* `ctx.restore();`
*/
CanvasRenderingContext2D.restore = function() { };
/**
* @desc Fills a circle clockwise between startAngle and endAngle where
* 0 is the start of the circle beginning at the 3 o'clock position on a
* watchface.
*
* If `startAngle` > `endAngle` nothing will be drawn, and if the difference
* between `startAngle` and `endAngle` exceeds 2π, a full circle will be drawn.
*
* `// Draw a filled circle<br>ctx.fillStyle = 'white';<br>ctx.rockyFillRadial(72, 84, 0, 30, 0, 2 * Math.PI);`
*
* @param {Number} x - The x-axis coordinate of the radial's center point
* @param {Number} y - The y-axis coordinate of the radial's center point
* @param {Number} innerRadius - The inner radius of the circle. Use 0 for a full circle
* @param {Number} outerRadius - The outer radius of the circle
* @param {Number} startAngle - Radial starting angle
* @param {Number} endAngle - Radial finishing angle. If smaller than `startAngle` nothing is drawn
*/
CanvasRenderingContext2D.rockyFillRadial = function(x, y, innerRadius, outerRadius, startAngle, endAngle) { };

View File

@@ -1,64 +0,0 @@
/**
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @namespace console
* @desc This provides an interface to the app's debugging console.
*
* If you're using {@link https://cloudpebble.net CloudPebble}, these logs
* will appear when you press 'View Logs' after launching your application.
*
* If you're using the local SDK, you can use the `$ pebble logs` command or:
*
* `$ pebble install --emulator basalt --logs`
*
* You can find out more about logging in our
* {@link /guides/debugging/debugging-with-app-logs/ Debugging with App Logs} guide.
*/
var console = new Object();
/**
* @desc Outputs a message to the app's debugging console.
*
* `console.log(rocky.watchInfo.platform);`
*
* @param {...Object} obj - One or more JavaScript objects to output. The string
* representations of each of these objects are appended together in the order
* listed and output.
*/
console.log = function (obj) { };
/**
* @desc Outputs a warning message to the app's debugging console.
*
* `console.warn('Something seems wrong');`
*
* @param {...Object} obj - One or more JavaScript objects to output. The string
* representations of each of these objects are appended together in the order
* listed and output.
*/
console.warn = function (obj) { };
/**
* @desc Outputs an error message to the app's debugging console.
*
* `console.error(JSON.stringify(obj));`
*
* @param {...Object} obj - One or more JavaScript objects to output. The string
* representations of each of these objects are appended together in the order
* listed and output.
*/
console.error = function (obj) { };

View File

@@ -1,121 +0,0 @@
/**
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @namespace Date
*
* @desc Creates a JavaScript Date instance that represents a single moment in
* time. Date objects are based on a time value that is the number of
* milliseconds since 1 January, 1970 UTC.
*
* `var d = new Date();`
*
* We fully implement standard JavaScript `Date` functions, such as: `getDay()`, `getHours()` etc.
*
* For full `Date` documentation see:
* {@link https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date}
*
* ### Locale Date Methods
*
* The locale date methods ({@link #toLocaleString toLocaleString},
* {@link #toLocaleTimeString toLocaleTimeString} and
* {@link #toLocaleDateString toLocaleDateString}) are currently limited in
* their initial implementation.
*
* Available **options**:
*
* **hour12**
*
* Use 12-hour time (as opposed to 24-hour time). Possible values are `true` and `false`; the default is locale dependent (Pebble setting).
*
* **weekday**
*
* The representation of the weekday. Possible values are "narrow", "short", "long".
*
* **year**
*
* The representation of the year. Possible values are "numeric", "2-digit".
*
* **month**
*
* The representation of the month. Possible values are "numeric", "2-digit", "narrow", "short", "long".
*
* **day**
*
* The representation of the day. Possible values are "numeric", "2-digit".
*
* **hour**
*
* The representation of the hour. Possible values are "numeric", "2-digit".
*
* **minute**
*
* The representation of the minute. Possible values are "numeric", "2-digit".
*
* **second**
*
* The representation of the second. Possible values are "numeric", "2-digit".
*
*
* Please note that locale based date and time functions have the following
* limitations at this time:
*
* * You cannot manually specify a locale, it's automatically based upon the
* current device settings. Locale is optional, or you can specify `undefined`.
*
* `console.log(d.toLocaleDateString());`
*
* * Only a single date/time value can be requested in each method call. Do
* NOT request multiple options. e.g. `{hour: 'numeric', minute: '2-digit'}`
*
* `console.log(d.toLocaleTimeString(undefined, {hour: 'numeric'}));`
*/
var Date = new Object();
/**
* @desc This method returns a string with a language sensitive representation
* of this date object.
*
* `d.toLocaleString();`
*
* @param {String} locale - (Optional) The name of the locale.
* @param {Object} options - (Optional) Only a single option is currently supported.
*/
Date.toLocaleString = function(locale, options) { };
/**
* @desc This method returns a string with a language sensitive representation
* of the date portion of this date object.
*
* `d.toLocaleTimeString(undefined, {hour: 'numeric'});`
*
* @param {String} locale - (Optional) The name of the locale.
* @param {Object} options - (Optional) Only a single option is currently supported.
*/
Date.toLocaleTimeString = function(locale, options) { };
/**
* @desc This method returns a string with a language sensitive representation
* of the time portion of this date object.
*
* `d.toLocaleDateString(undefined, {weekday: 'long'});`
*
* @param {String} locale - (Optional) The name of the locale.
* @param {Object} options - (Optional) Only a single option is currently supported.
*/
Date.toLocaleDateString = function() { };

View File

@@ -1,58 +0,0 @@
/**
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Global Functions, Members, and Typedefs
/**
* @desc Calls a function after a specified delay.
*
* `var timeoutId = setTimeout(function(...){}, 10000);`
*
* @returns {Number} timeoutId - The ID of the timeout
* @param {Function} fct - The function to execute
* @param {Number} delay - The delay (in ms)
*/
setTimeout = function(fct, delay) { };
/**
* @desc Clears the delay set by ``setTimeout``.
*
* `clearTimeout(timeoutId);`
*
* @param {Number} timeoutId - The ID of the timeout you wish to clear.
*/
clearTimeout = function(timeoutId) { };
/**
* @desc Repeatedly calls a function, with a fixed time delay between
* each call.
*
* `var intervalId = setInterval(function(...){}, 10000);`
*
* @returns {Number} intervalId - The ID of the interval
* @param {Function} fct - The function to execute
* @param {Number} delay - The delay (in ms)
*/
setInterval = function(fct, delay) { };
/**
* @desc Clears the interval set by ``setInterval``.
*
* `clearInterval(intervalId);`
*
* @param {Number} intervalId - The ID of the interval you wish to clear
*/
clearInterval = function(intervalId) { };

View File

@@ -1,262 +0,0 @@
/**
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @namespace rocky
*
* @desc Provides an interface for interacting with application context and
* events. Developers can access the Rocky object with the following line of
* code:
*
* `var rocky = require('rocky');`
*
*/
var rocky = {
/**
* @typedef {Object} WatchInfo
* @desc Provides information about the currently connected Pebble smartwatch.
*
* @property {String} model - The name of the Pebble model. (e.g. pebble_time_round_silver_20mm)
* @property {String} platform - The name of the Pebble platform. (e.g. basalt)
* @property {String} language - Not available yet.
* @property {String} firmware - An object with the following fields:
* * `major` - The major version of the smartwatch's firmware.
* * `minor` - The minor version of the smartwatch's firmware.
* * `patch` - The patch version of the smartwatch's firmware.
* * `suffix` - The suffix of the smartwatch's firmware. (e.g. beta3)
*/
/**
* @typedef {Object} UserPreferences
* @desc Provides access to user related settings from the currently connected Pebble smartwatch.
* The size itself will vary between platforms, see the
* {@link /guides/user-interfaces/content-size/ ContentSize guide} for more information.
*
* @property {String} contentSize - Pebble > System > Notifications > Text Size:
* * `small` - Not available on Emery.
* * `medium` - The default setting.
* * `large` - The default setting on Emery.
* * `x-large` - Only available on Emery.
*/
/**
* @typedef {Function} RockyDrawCallback
* @desc The callback function signature to be used with the draw {@link #on event}.
*
* @param {Object} event - An object containing information about the event:
* * `context` - A {@link /docs/rockyjs/CanvasRenderingContext2D CanvasRenderingContext2D}
* object that can be used to draw information on the disply.
*/
/**
* @typedef {Function} RockyTickCallback
* @desc The callback function signature to be used with the `secondchange`,
* `minutechange`, `hourchange` and `daychange` {@link #on events}.
*
* In addition to firing these tick events at the appropriate time change,
* they are also emitted when the application starts.
*
* @param {Object} event - An object containing information about the event:
* * `date` - A JavaScript
* {@link http://www.w3schools.com/jsref/jsref_obj_date.asp date} object
* representing the current time.
*/
/**
* @typedef {Function} RockyMessageCallback
* @desc The callback function signature to be used with the `message`
* {@link #on event}.
*
* @param {Object} event - An object containing information about the event:
* * `type` - The type of event which was triggered.
* * `data` - The data sent within the message.
*/
/**
* @typedef {Function} RockyPostMessageErrorCallback
* @desc The callback function signature to be used with the `postmessageerror`
* {@link #on event}.
*
* @param {Object} event - An object containing information about the event:
* * `type` - The type of event which was triggered.
* * `data` - The data failed to send within the message.
*/
/**
* @typedef {Function} RockyPostMessageConnectedCallback
* @desc The callback function signature to be used with the `postmessageconnected`
* {@link #on event}.
*
* @param {Object} event - An object containing information about the event:
* * `type` - The type of event which was triggered.
*/
/**
* @typedef {Function} RockyPostMessageDisconnectedCallback
* @desc The callback function signature to be used with the `postmessagedisconnected`
* {@link #on event}.
*
* @param {Object} event - An object containing information about the event:
* * `type` - The type of event which was triggered.
*/
/**
* @typedef {Function} RockyMemoryPressureCallback
* @desc The callback function signature to be used with the `memorypressure`
* {@link #on event}.
*
* @param {Object} event - An object containing information about the event:
* * `level` (String) - The current level of memory pressure.
*
* * `high` - This is a critical level, indicating that the application will
* be terminated if memory isn't immediately free'd.
*
* Important Notes:
* - Avoid creating any new objects/arrays/strings when this level is raised.
* - Drop object properties you don't need using the `delete` operator or by assigning `undefined` to it.
* - Don't use the `in` operator in the handler for large objects/arrays. Avoid `for (var x in y)` due to memory constraints.
* - Array has large memory requirements for certain operations/methods. Avoid `Array.pop()`, `Array.slice` and length assignment `Array.length = 123`, on large arrays.
*
* * `normal` - Not yet implemented.
*
* * `low` - Not yet implemented.
*/
/**
* @desc A {@link #WatchInfo WatchInfo} object containing information about the
* connected Pebble smartwatch.
*
* `console.log(rocky.watchInfo.model);<br>&gt; pebble_2_hr_lime`
*
*/
watchInfo,
/**
* @desc A {@link #UserPreferences UserPreferences} object access to user related settings from the currently connected Pebble smartwatch.
*
* `console.log(rocky.userPreferences.contentSize);<br>&gt; medium`
*
*/
userPreferences
};
/**
* @desc Attaches an event handler to the specified events. You may subscribe
* with multiple handlers, but at present there is no way to unsubscribe.
*
* `rocky.on('minutechange', function() {...});`
*
* #### Event Type Options
*
* Possible values:
*
* * `draw` - Provide a {@link #RockyDrawCallback RockyDrawCallback} as the
* callback. The draw event is being emitted after each call to
* {@link #requestDraw requestDraw} but at most once for each screen update,
* even if {@link #requestDraw requestDraw} is called frequently the 'draw'
* event might also fire at other meaningful times (e.g. upon launch).
* * `secondchange` - Provide a {@link #RockyTickCallback RockyTickCallback} as the
* callback. The secondchange event is emitted every time the clock's second changes.
* * `minutechange` - Provide a {@link #RockyTickCallback RockyTickCallback} as the
* callback. The minutechange event is emitted every time the clock's minute changes.
* * `hourchange` - Provide a {@link #RockyTickCallback RockyTickCallback} as the
* callback. The hourchange event is emitted every time the clock's hour changes.
* * `daychange` - Provide a {@link #RockyTickCallback RockyTickCallback} as the
* callback. The daychange event is emitted every time the clock's day changes.
* * `memorypressure` - Provides a {@link #RockyMemoryPressureCallback RockyMemoryPressureCallback}. The
* event is emitted every time there is a notable change in available system memory.
* You can see an example implementation of memory pressure handling {@link https://github.com/pebble-examples/rocky-memorypressure here}.
* * `message` - Provide a {@link #RockyMessageCallback RockyMessageCallback}
* as the callback. The message event is emitted every time the application
* receives a {@link #postMessage postMessage} from the mobile companion.
* * `postmessageconnected` - Provide a {@link #RockyPostMessageConnectedCallback RockyPostMessageConnectedCallback}
* as the callback. The event may be emitted immediately upon subscription,
* if the subsystem is already connected. It is also emitted when connectivity is established.
* * `postmessagedisconnected` - Provide a {@link #RockyPostMessageDisconnectedCallback RockyPostMessageDisconnectedCallback}
* as the callback. The event may be emitted immediately upon subscription,
* if the subsystem is already disconnected. It is also emitted when connectivity is lost.
* * `postmessageerror` - Provide a {@link #RockyPostMessageErrorCallback RockyPostMessageErrorCallback}
* as the callback. The event is emitted when a transmission error occurrs. The type
* of error is not provided, but the message has not been delivered.
*
* @param {String} type - The event being subscribed to.
* @param {Function} callback - A callback function that will be executed when
* the event occurs. See below for more details.
*
*/
rocky.on = function(type, callback) { };
/**
* @desc Attaches an event handler to the specified events. Synonymous with
* [rocky.on()](#on).
*
* `rocky.addEventListener(type, callback);`
*
* @param {String} type - The event being subscribed to.
* @param {Function} callback - A callback function that will be executed when
* the event occurs. See below for more details.
*/
rocky.addEventListener = function(type, callback) { };
/**
* @desc Remove an existing event listener previously registered with
* [rocky.on()](#on) or [rocky.addEventListener()](#addEventListener).
*
* @param {String} type - The type of the event listener to be removed. See
* [rocky.on()](#on) for a list of available event types.
* @param {Function} callback - The existing developer-defined function that was
* previously registered.
*/
rocky.removeEventListener = function(type, callback) { };
/**
* @desc Remove an existing event handler from the specified events. Synonymous
* with [rocky.removeEventListener()](#removeEventListener).
*
* `rocky.off(type, callback);`
*
* @param {String} type - The type of the event listener to be removed. See
* [rocky.on()](#on) for a list of available event types.
* @param {Function} callback - The existing developer-defined function that was
* previously registered.
*/
rocky.off = function(type, callback) { };
/**
* @desc Sends a message to the mobile companion component. Please be aware
* that messages should be kept concise. Each message is queued, so
* `postMessage()` can be called multiple times immediately. If there is a momentary loss of connectivity, queued
* messages may still be delivered, or automatically removed from the queue
* after a few seconds of failed connectivity. Any transmission failures, or
* out of memory errors will be raised via the `postmessageerror` event.
*
* `rocky.postMessage({cmd: 'fetch'});`
*
* @param {Object} data - An object containing the data to deliver to the mobile
* device. This will be received in the `data` field of the `event`
* delivered to the `on('message', ...)` handler.
*/
rocky.postMessage = function(data) { };
/**
* @desc Flags the canvas (display) as requiring a redraw. Invoking this method
* will cause the {@link #on draw event} to be emitted. Only 1 draw event
* will occur, regardless of how many times the redraw is requested before
* the next draw event.
*
* `rocky.on('secondchange', function(e) {<br>&nbsp;&nbsp;rocky.requestDraw();<br>});`
*/
rocky.requestDraw = function() { };

View File

@@ -1,153 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
module Pebble
# DocClass is a special type of DocElement for structs and unions.
# It acts like a DocGroup in that it parses an XML file, but it acts like a
# DocMember in that it belongs to a group etc.
class DocClass < DocElement
attr_reader :summary, :description, :kind, :position, :id, :name
def initialize(root, dir, platform, kind, id, group)
super(root, platform)
@dir = dir
@group = group
@kind = kind
@children = []
@xml = {}
@code = id
@doxygen_processor = DoxygenProcessor.new(platform)
load_xml(platform)
end
def load_xml(platform)
@xml[platform] = Nokogiri::XML(File.read("#{@dir}/#{platform}/xml/#{@kind}_#{@code}.xml"))
@data[platform] = {}
@name = @xml[platform].at_css('compounddef > compoundname').content.to_s
@id = @xml[platform].at_css('compounddef')['id']
@path = "#{@group.path}##{@name}"
create_members(platform)
end
def to_liquid
{
'name' => @name,
'summary' => @summary,
'description' => @description,
'url' => url,
'children' => @children,
'data' => @data,
'platforms' => @xml.keys,
'uniform' => uniform?
}
end
def process(mapping)
@xml.each do |platform, xml|
@data[platform]['summary'] = @doxygen_processor.process_summary(
xml.at_css('compounddef > briefdescription'), mapping
)
description = xml.at_css('compounddef > detaileddescription')
process_simplesects(description, mapping, platform)
@data[platform]['description'] = @doxygen_processor.process_description(
description, mapping)
process_members(mapping, platform)
end
@children = @children.reject { |child| child.name.match(/^@/) }
@children.sort! { |m, n| m.position <=> n.position }
end
def uniform?
identical = @data['aplite'].to_json == @data['basalt'].to_json
identical &&= @children.all?(&:uniform?)
identical
end
private
def create_members(platform)
@xml[platform].css('memberdef').each do |child|
variable = DocClassVariable.new(@root, child, @group, platform)
existing = @children.select { |ex| ex.name == variable.name }.first
if existing.nil?
@children << variable
else
existing.add_platform(platform, child)
end
end
end
def process_members(mapping, platform)
@children.each { |child| child.process(mapping, platform) }
end
end
# DocClassVariable is a DocElement subclass that handles the members (or
# variables) of a struct or union.
class DocClassVariable < DocElement
attr_reader :name, :position
def initialize(root, node, group, platform)
super(root, platform)
@name = node.at_css('name').content.to_s
@group = group
@nodes = { platform => node }
@platforms = [platform]
@path = "#{@group.path}##{@name}"
@position = node.at_css(' > location')['line'].to_i
end
def add_platform(platform, node)
@nodes[platform] = node
@platforms << platform
@data[platform] = {}
end
def to_liquid
{
'name' => @name,
'data' => @data,
'url' => url,
'type' => @type,
'platforms' => @platforms
}
end
def uniform?
@data['aplite'].to_json == @data['basalt'].to_json
end
def process(mapping, platform)
return unless @platforms.include? platform
@data[platform]['summary'] = @doxygen_processor.process_summary(
@nodes[platform].at_css('briefdescription'), mapping
)
description = @nodes[platform].at_css('detaileddescription')
process_simplesects(description, mapping, platform)
process_type(mapping, platform)
@data[platform]['description'] = @doxygen_processor.process_description(
description, mapping)
end
def process_type(mapping, platform)
if @nodes[platform].at_css('type > ref').nil?
@data[platform]['type'] = @nodes[platform].at_css('type').content.to_s
else
type_node = @nodes[platform].at_css('type').clone()
@doxygen_processor.process_node_ref(type_node.at_css('ref'), mapping)
@data[platform]['type'] = type_node.to_html.to_s
end
end
end
end

View File

@@ -1,98 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
module Pebble
# DocElement is an abstract C Documentation class that is subclasses for
# each of the various items that build up a documentation page, symbol or
# tree item.
class DocElement
KNOWN_SECT_TYPES = %w(return note)
attr_reader :url
def initialize(root, platform)
@root = root
@data = {}
@data[platform] = {}
@doxygen_processor = DoxygenProcessor.new(platform)
end
def to_symbol
{
name: @name,
url: url,
summary: default_data('summary')
}
end
def to_mapping
{
id: @id,
url: url
}
end
private
def default_data(key)
return @data['basalt'][key] unless @data['basalt'].nil? || @data['basalt'][key].nil?
return @data['aplite'][key] unless @data['aplite'].nil? || @data['aplite'][key].nil?
''
end
def url
"#{@root}#{@path}"
end
def add_data(type, value, platform)
@data[platform] = {} if @data[platform].nil?
@data[platform][type] = [] if @data[platform][type].nil?
@data[platform][type] << value
end
def process_simplesects(node, mapping, platform)
if node.name.to_s == 'detaileddescription'
desc = node
else
desc = node.at_css('detaileddescription')
end
return if desc.nil?
desc.css('simplesect').each do |sect|
if KNOWN_SECT_TYPES.include?(sect['kind'])
process_simplesect_basic(sect, mapping, platform)
elsif sect['kind'] == 'see'
process_simplesect_see(sect, mapping, platform)
end
end
end
def process_simplesect_basic(sect, mapping, platform)
value = @doxygen_processor.process_summary(sect.clone, mapping)
add_data(sect['kind'], value, platform)
sect.remove
end
def process_simplesect_see(sect, mapping, platform)
if sect.at_css('para > ref').nil?
add_data(sect['kind'],
@doxygen_processor.process_paragraph(sect.at_css('para'),
mapping), platform)
else
see_node = sect.at_css('para > ref').clone
@doxygen_processor.process_node_ref(see_node, mapping)
add_data(sect['kind'], see_node.to_html.to_s, platform)
end
sect.remove
end
end
end

View File

@@ -1,58 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
module Pebble
# DocEnumValue is a DocElement that is one of the possible values of an enum.
class DocEnumValue < DocElement
attr_reader :position, :summary, :id, :platforms, :name, :data
def initialize(root, node, group, platform)
super(root, platform)
@name = node.at_css('name').content.to_s
@id = node['id']
@group = group
@path = "#{@group.path}##{@name}"
@nodes = { platform => node }
@platforms = [platform]
@doxygen_processor = DoxygenProcessor.new(platform)
end
def add_platform(node, platform)
@nodes[platform] = node
@platforms << platform
@data[platform] = {}
end
def process(mapping, platform)
return unless @platforms.include? platform
process_simplesects(@nodes[platform], mapping, platform)
@data[platform]['summary'] = @doxygen_processor.process_summary(
@nodes[platform].at_css('briefdescription'), mapping
)
end
def uniform?
data['aplite'].to_json == data['basalt'].to_json
end
def to_liquid
{
'name' => @name,
'data' => @data,
'url' => url,
'platforms' => @platforms
}
end
end
end

View File

@@ -1,178 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require_relative 'doc_element.rb'
require_relative 'doc_member.rb'
require_relative 'doc_class.rb'
require_relative 'doxygen_processor.rb'
module Pebble
# A DocGroup is a a collection of members, structs and subgroups that will
# become a page in the C documentation.
class DocGroup < DocElement
attr_accessor :groups, :members, :name, :path, :menu_path, :classes, :id
def initialize(root, dir, platform, id, menu_path = [])
super(root, platform)
@dir = dir
@menu_path = Array.new(menu_path)
@xml = {}
@groups = []
@members = []
@classes = []
@group_id = id
@doxygen_processor = DoxygenProcessor.new(platform)
@root = root
load_xml(platform)
end
def load_xml(platform)
@xml[platform] = Nokogiri::XML(File.read("#{@dir}/#{platform}/xml/group___#{@group_id}.xml"))
@id = @xml[platform].at_css('compounddef')['id']
@name = @xml[platform].at_css('compounddef > title').content.to_s
@menu_path << @name if @path.nil?
@path = @menu_path.join('/').gsub(' ', '_') + '/'
create_descendents(platform)
end
def process(mapping, platform)
return if @xml[platform].nil?
@data[platform] = {} if @data[platform].nil?
@data[platform]['summary'] = @doxygen_processor.process_summary(
@xml[platform].at_css('compounddef > briefdescription'), mapping)
description = @xml[platform].at_css('compounddef > detaileddescription')
process_simplesects(description, mapping, platform)
@data[platform]['description'] = @doxygen_processor.process_description(
description, mapping)
process_descendents(mapping, platform)
end
def to_page(site)
PageDocC.new(site, @root, site.source, "#{@path}index.html", self)
end
def to_branch
{
'name' => @name,
'url' => url,
'children' => @groups.map(&:to_branch),
'summary' => default_data('summary')
}
end
def mapping_array
mapping = [to_mapping]
@groups.each { |group| mapping += group.mapping_array }
@members.each { |member| mapping << member.to_mapping }
@classes.each { |cls| mapping << cls.to_mapping }
mapping
end
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
def to_liquid
{
'name' => @name,
'url' => url,
'path' => @menu_path,
'groups' => @groups,
'members' => @members,
'functions' => @members.select { |member| member.kind == 'function' },
'enums' => @members.select { |member| member.kind == 'enum' },
'defines' => @members.select { |member| member.kind == 'define' },
'typedefs' => @members.select { |member| member.kind == 'typedef' },
'structs' => @classes.select { |member| member.kind == 'struct' },
'unions' => @classes.select { |member| member.kind == 'union' },
'data' => @data,
'basalt_only' => !@xml.key?('aplite'),
'summary' => default_data('summary'),
'description' => default_data('description')
}
end
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
private
def create_descendents(platform)
create_inner_groups(platform)
create_members(platform)
create_inner_classes(platform)
@members.sort! { |m, n| m.position <=> n.position }
end
def create_inner_groups(platform)
@xml[platform].css('innergroup').each do |child|
id = child['refid'].sub(/^group___/, '')
new_group = DocGroup.new(@root, @dir, platform, id, @menu_path)
group = @groups.select { |grp| new_group.name == grp.name }.first
if group.nil?
@groups << new_group
else
group.load_xml(platform)
end
end
end
def create_members(platform)
@xml[platform].css('memberdef').map do |child|
new_member = DocMember.new(@root, child, self, platform)
member = @members.select { |mem| mem.name == new_member.name }.first
if member.nil?
@members << new_member
else
member.add_platform(platform, child)
end
end
end
def create_inner_classes(platform)
@xml[platform].css('innerclass').map do |child|
next if child.content.to_s.match(/__unnamed__/)
next if child.content.to_s.match(/\./)
if child['refid'].match(/^struct_/)
create_struct(child, platform)
elsif child['refid'].match(/^union_/)
create_union(child, platform)
end
end
end
def create_struct(node, platform)
id = node['refid'].sub(/^struct_/, '')
new_struct = DocClass.new(@root, @dir, platform, 'struct', id, self)
struct = @classes.select { |str| new_struct.name == str.name }.first
if struct.nil?
@classes << new_struct
else
struct.load_xml(platform)
end
end
def create_union(node, platform)
id = node['refid'].sub(/^union_/, '')
new_union = DocClass.new(@root, @dir, platform, 'union', id, self)
union = @classes.select { |un| un.name == new_union.name }.first
if union.nil?
@classes << new_union
else
union.load_xml(platform)
end
end
def process_descendents(mapping, platform)
@groups.each { |group| group.process(mapping, platform) }
@members.each { |member| member.process(mapping, platform) }
@classes.each { |member| member.process(mapping) }
end
end
end

View File

@@ -1,165 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require_relative 'doc_enum_value.rb'
module Pebble
# A DocMember is a function, enum, typedef that will become a symbol
# and be a part of a documentation page. Belongs to a DocGroup.
class DocMember < DocElement
attr_accessor :children, :kind, :name, :summary, :children, :position, :data, :id
def initialize(root, node, group, platform)
super(root, platform)
@group = group
@children = []
@platforms = [platform]
@nodes = { platform => node }
@name = node.at_css('name').content.to_s
@kind = node['kind']
@id = node['id']
@path = "#{@group.path}##{@name}"
@position = node.at_css(' > location')['line'].to_i
@doxygen_processor = DoxygenProcessor.new(platform)
create_enum_values(node, platform) if @kind == 'enum'
end
def add_platform(platform, node)
@platforms << platform
@nodes[platform] = node
@data[platform] = {}
create_enum_values(node, platform) if @kind == 'enum'
end
def to_liquid
{
'name' => @name,
'url' => url,
'children' => @children,
'position' => @position,
'data' => @data,
'uniform' => uniform?,
'platforms' => @platforms
}
end
def process(mapping, platform)
return unless @platforms.include? platform
@data[platform]['summary'] = @doxygen_processor.process_summary(
@nodes[platform].at_css(' > briefdescription'), mapping
)
process_data(@nodes[platform], mapping, platform)
@data[platform]['description'] = @doxygen_processor.process_description(
@nodes[platform].at_css(' > detaileddescription'), mapping
)
@children.each { |child| child.process(mapping, platform) }
end
def uniform?
identical = data['aplite'].to_json == data['basalt'].to_json
identical &&= children.all?(&:uniform?) if @kind == 'enum'
identical
end
private
def create_enum_values(node, platform)
node.css('enumvalue').each do |value|
enum_value = DocEnumValue.new(@root, value, @group, platform)
existing_value = @children.select { |ev| ev.name == enum_value.name }.first
if existing_value.nil?
@children << enum_value
else
existing_value.add_platform(value, platform)
end
end
end
def process_data(node, mapping, platform)
process_typedef(node, mapping, platform) if @kind == 'typedef'
process_function(node, mapping, platform) if @kind == 'function'
process_define(node, mapping, platform) if @kind == 'define'
process_simplesects(node, mapping, platform)
end
def process_typedef(node, mapping, platform)
process_return_type(node, mapping, platform)
@data[platform]['argsstring'] = node.at_css('argsstring').content.to_s
process_parameter_list(node, mapping, platform)
end
def process_function(node, mapping, platform)
process_return_type(node, mapping, platform)
process_params(node, mapping, platform) unless node.css('param').nil?
process_parameter_list(node, mapping, platform)
end
def process_define(node, mapping, platform)
unless node.at_css('initializer').nil?
@data[platform]['initializer'] = process_to_html(
node.at_css('initializer'), mapping
)
end
process_return_type(node, mapping, platform)
process_parameter_list(node, mapping, platform)
process_params(node, mapping, platform) unless node.css('param').nil?
end
def process_return_type(node, mapping, platform)
@data[platform]['type'] = process_to_html(node.at_css('> type'), mapping)
end
def process_params(node, mapping, platform)
@data[platform]['params'] = node.css('param').map do |elem|
params = {}
unless elem.at_css('declname').nil?
params['name'] = elem.at_css('declname').content.to_s
end
unless elem.at_css('type').nil?
params['type'] = process_to_html(elem.at_css('type'), mapping)
end
unless elem.at_css('defname').nil?
params['name'] = elem.at_css('defname').content.to_s
end
params
end
end
def process_to_html(node, mapping)
return '' if node.nil?
node.css('ref').each do |ref|
@doxygen_processor.process_node_ref(ref, mapping)
end
node.inner_html.to_s
end
def process_parameter_list(node, mapping, platform)
return if node.at_css('parameterlist').nil?
parameter_list = node.at_css('parameterlist').clone
node.at_css('parameterlist').remove
@data[platform]['parameters'] = parameter_list.css('parameteritem').map do |item|
{
'name' => get_parameter_name(item),
'summary' => @doxygen_processor.process_summary(item.at_css('parameterdescription'), mapping)
}
end
end
def get_parameter_name(item)
name = item.at_css('parameternamelist > parametername')
direction = name.attr('direction').to_s
direction.nil? || direction == '' ? name.content.to_s : "#{name.content.to_s} (#{direction})"
end
end
end

View File

@@ -1,154 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
module Pebble
# Class of methods for processing Doxygen XML into 'sane' HTML.
# rubocop:disable Metrics/ClassLength
class DoxygenProcessor
def initialize(platform)
@platform = platform
end
def process_summary(node, mapping)
process_description(node, mapping)
end
def process_description(node, mapping)
return '' if node.nil?
node.children.map { |para| process_paragraph(para, mapping) }.join("\n").strip
end
# rubocop:disable Metrics/MethodLength, Methods/CyclomaticComplexity
# rubocop:disable Methods/AbcSize
def process_paragraph(node, mapping)
return '' if node.nil?
node.name = 'p'
node.children.each do |child|
case child.name
when 'ref'
process_node_ref(child, mapping)
when 'programlisting'
process_code(child)
when 'simplesect'
# puts node.content.to_s
# process_blockquote(child)
when 'heading'
process_node_heading(child)
when 'htmlonly'
process_node_htmlonly(child)
when 'itemizedlist'
process_list(child, mapping)
when 'image'
process_image(child)
when 'computeroutput'
process_computer_output(child)
when 'emphasis'
child.name = 'em'
when 'bold'
child.name = 'strong'
when 'linebreak'
child.name = 'br'
when 'preformatted'
child.name = 'pre'
when 'ndash'
child.name = 'span'
child.content = '-'
when 'ulink'
child.name = 'a'
child['href'] = child['url'].sub(%r{^https?://developer.pebble.com/}, '/')
child.remove_attribute('url')
when 'text'
# SKIP!
else
# puts child.name, node.content.to_s
end
end
node.to_html.to_s.strip
end
# rubocop:enable Metrics/MethodLength, Methods/CyclomaticComplexity
# rubocop:enable Methods/AbcSize
def process_code(node)
xml = node.to_xml.gsub('<sp/>', ' ')
doc = Nokogiri::XML(xml)
highlight = Pygments.highlight(doc.content.to_s.strip, lexer: 'c')
node.content = ''
node << Nokogiri::XML(highlight).at_css('pre')
node.name = 'div'
node['class'] = 'highlight'
end
def process_node_ref(child, mapping)
child.name = 'a'
map = mapping.select { |m| m[:id] == child['refid'] }.first
child['href'] = map[:url] unless map.nil?
end
def process_node_heading(node)
node.name = 'h' + node['level']
end
def process_node_htmlonly(node)
decoder = HTMLEntities.new
xml = Nokogiri::XML('<root>' + decoder.decode(node.content) + '</root>')
node_count = xml.root.children.size
process_node_htmlonly_simple(node, xml) if node_count == 2
process_node_htmlonly_complex(node, xml) if node_count > 2
end
def process_node_htmlonly_simple(node, xml)
child = xml.at_css('root').children[0]
node.name = child.name
child.attributes.each { |key, value| node[key] = value }
node.content = child.content
end
def process_node_htmlonly_complex(node, xml)
node.name = 'div'
node.content = ''
node << xml.root.children
end
def process_blockquote(node)
node.name = 'blockquote'
node['class'] = 'blockquote--' + node['kind']
process_paragraph(node.children[0]) if node.children[0].name == 'para'
node.to_html.to_s
end
def process_list(node, mapping)
node.name = 'ul'
node.children.each do |child|
process_list_item(child, mapping)
end
end
def process_list_item(node, mapping)
node.name = 'li'
node.children.each do |child|
process_paragraph(child, mapping) if child.name == 'para'
end
end
def process_image(node)
node.name = 'img'
node['src'] = "/assets/images/docs/c/#{@platform}/#{node['name']}"
end
def process_computer_output(node)
node.name = 'code'
end
end
# rubocop:enable Metrics/ClassLength
end

View File

@@ -1,49 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
module Pebble
class Documentation
LANGUAGE = ''
def initialize(site)
@site = site
@symbols = []
@pages = []
@tree = []
end
def load_symbols(symbols)
symbols.concat(@symbols)
end
def create_pages(pages)
pages.concat(@pages)
end
def build_tree(tree)
tree.concat(@tree)
end
private
def add_symbol(symbol)
symbol[:language] = language
symbol[:summary] = symbol[:summary].strip unless symbol[:summary].nil?
@symbols << symbol
end
def language
LANGUAGE
end
end
end

View File

@@ -1,189 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'pygments'
require 'zip'
require 'nokogiri'
require 'htmlentities'
require_relative 'c_docs/doc_group.rb'
module Pebble
# Pebble C documentation processing class.
class DocumentationC < Documentation
MASTER_GROUP_IDS = %w(foundation graphics u_i smartstrap worker standard_c)
def initialize(site, source, root, language='c')
super(site)
@site = site
@url_root = root
@source = source
@tmp_dir = 'tmp/docs/c'
@groups = []
@language = language
run
end
private
def language
@language
end
def run
cleanup
download_and_extract(@source, @tmp_dir)
hack_smartstraps
process
add_images
end
def cleanup
FileUtils.rmtree @tmp_dir
end
def download_and_extract(zip, folder)
open(zip) do | zf |
Zip::File.open(zf.path) do | zipfile |
zipfile.each do | entry |
path = File.join(folder, entry.name).sub('/doxygen_sdk/', '/')
FileUtils.mkdir_p(File.dirname(path))
zipfile.extract(entry, path) unless File.exist?(path)
end
end
end
end
# This is a hack to get around a limitation with the documentation generator.
# At present, it cannot handle the situation where a top level doc group exists on
# Basalt but not Aplite.
# Smartstraps is the only group that fits this pattern at the moment.
# This hack copies the XML doc from the Basalt folder to the Aplite folder and removes
# all of its contents.
def hack_smartstraps
basalt_xml = Nokogiri::XML(File.read("#{@tmp_dir}/basalt/xml/group___smartstrap.xml"))
basalt_xml.search('.//memberdef').remove
basalt_xml.search('.//innerclass').remove
basalt_xml.search('.//sectiondef').remove
File.open("#{@tmp_dir}/aplite/xml/group___smartstrap.xml", 'w') do |file|
file.write(basalt_xml.to_xml)
end
end
def process
DocumentationC::MASTER_GROUP_IDS.each do |id|
@groups << DocGroup.new(@url_root, @tmp_dir, 'aplite', id)
end
@groups.each { |group| group.load_xml('basalt') }
mapping = []
@groups.each { |group| mapping += group.mapping_array }
@groups.each do |group|
group.process(mapping, 'aplite')
group.process(mapping, 'basalt')
end
add_symbols(@groups)
@groups.each { |group| @tree << group.to_branch }
add_pages(@groups)
add_redirects(mapping)
end
def add_images
move_images('aplite')
move_images('basalt')
images = Dir.glob("#{@tmp_dir}/assets/images/**/*.png")
images.each do |img|
source = File.join(@site.source, '../tmp/docs/c/')
if File.exists?(img)
img.sub!('tmp/docs/c', '')
@site.static_files << Jekyll::StaticFile.new(@site, source, '', img)
end
end
end
def move_images(platform)
images = Dir.glob("#{@tmp_dir}/#{platform}/**/*.png")
dir = File.join(@tmp_dir, 'assets', 'images', 'docs', 'c', platform)
FileUtils.mkdir_p(dir)
images.each do |img|
FileUtils.cp(img, File.join(dir, File.basename(img)))
end
end
# TODO: Make the groups handle their own subgroups and members etc
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
def add_symbols(groups)
groups.each do |group|
add_symbol(group.to_symbol)
group.members.each do |member|
add_symbol(member.to_symbol)
member.children.each do |child|
add_symbol(child.to_symbol)
end
end
group.classes.each do |child|
add_symbol(child.to_symbol)
# OPINION: I don't think we want to have struct members as symbols.
# struct.children.each do |child|
# add_symbol(child.to_symbol)
# end
end
add_symbols(group.groups)
end
end
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
def add_pages(groups)
groups.each do |group|
page = group.to_page(@site)
page.set_language(@language)
@pages << page
add_pages(group.groups)
end
end
def add_redirects(mapping)
mapping.each do |map|
next if map[:id].match(/_1/)
@site.pages << Jekyll::RedirectPage.new(@site, @site.source, @url_root, map[:id] + '.html', map[:url])
end
end
end
# Jekyll Page subclass for rendering the C documentation pages.
class PageDocC < Jekyll::Page
attr_reader :group
def initialize(site, root, base, dir, group)
@site = site
@base = base
@dir = root
@name = dir
@group = group
process(@name)
read_yaml(File.join(base, '_layouts', 'docs'), 'c.html')
data['title'] = @group.name
data['platforms'] = %w(aplite basalt)
end
def set_language(language)
data['docs_language'] = language
end
def to_liquid(attrs = ATTRIBUTES_FOR_LIQUID)
super(attrs + %w(group))
end
end
end

View File

@@ -1,120 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'zip'
module Pebble
# Rock.js documentation processing class.
class DocumentationJs < Documentation
def initialize(site, source, root, language, preview = false)
super(site)
@url_root = root
@language = language
@preview = preview
json = site.data[source]
json.each { |js_module| process_module(js_module) }
end
private
def process_module(js_module)
js_module[:path] = js_module['name']
js_module[:url] = module_url(js_module)
js_module[:processed_functions] = []
js_module[:processed_members] = []
js_module[:processed_typedefs] = []
js_module[:children] = []
process_members(js_module)
add_to_tree(js_module)
# Create and add the page
page = PageDocJS.new(@site, module_url(js_module), js_module)
page.set_data(@language, @preview)
@pages << page
end
def process_members(js_module)
js_module['members'].each do |type, members|
members.each do |member|
kind = member.key?('kind') ? member['kind'] : 'member'
processed_type = 'processed_' + kind + 's'
url = child_url(js_module, member)
symbol = {
:name => member['name'],
:description => member['description'],
:type => member['type'],
:returns => member['returns'],
:params => member['params'],
:properties => member['properties'],
:url => url,
:kind => kind,
:summary => member['summary']
}
add_symbol(symbol)
js_module[:children].push(symbol)
js_module[processed_type.to_sym].push(symbol)
end
end
end
def add_to_tree(js_module)
@tree << js_module
end
def module_url(js_module)
"#{@url_root}#{js_module['name']}/"
end
def child_url(js_module, child)
"#{module_url(js_module)}##{child['name']}"
end
def child_path(js_module, child)
[js_module['name'], child['name']].join('.')
end
def language
@language
end
end
# Jekyll Page subclass for rendering the JS documentation pages.
class PageDocJS < Jekyll::Page
attr_reader :js_module
def initialize(site, url, js_module)
@site = site
@base = site.source
@dir = url
@name = 'index.html'
@js_module = JSON.parse(js_module.to_json)
process(@name)
read_yaml(File.join(@base, '_layouts', 'docs'), 'js.html')
data['title'] = js_module['name']
end
def set_data(language, preview)
data['docs_language'] = language
data['preview'] = preview
end
def to_liquid(attrs = ATTRIBUTES_FOR_LIQUID)
super(attrs + %w(js_module))
end
end
end

View File

@@ -1,203 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'zip'
require 'nokogiri'
require_relative 'pebble_documentation'
# TODO: Error handling.
# TODO: Introduce some DRY
# TODO: Fix the internal links!
# TODO: Bring back the summarys which I broke.
# TODO: Android Index Page
module Pebble
class DocumentationPebbleKitAndroid < Documentation
def initialize(site, source)
super(site)
@path = '/docs/pebblekit-android/'
open(source) do | zf |
Zip::File.open(zf.path) do | zipfile |
entry = zipfile.glob('javadoc/overview-summary.html').first
summary = Nokogiri::HTML(entry.get_input_stream.read)
process_summary(zipfile, summary)
@pages << PageDocPebbleKitAndroid.new(@site, @site.source, 'docs/pebblekit-android/com/constant-values/', 'Constant Values', process_html(Nokogiri::HTML(zipfile.glob('javadoc/constant-values.html').first.get_input_stream.read).at_css('.constantValuesContainer').to_html, '/docs/pebblekit-android/'), nil)
@pages << PageDocPebbleKitAndroid.new(@site, @site.source, 'docs/pebblekit-android/com/serialized-form/', 'Serialized Form', process_html(Nokogiri::HTML(zipfile.glob('javadoc/serialized-form.html').first.get_input_stream.read).at_css('.serializedFormContainer').to_html, '/docs/pebblekit-android/'), nil)
end
end
end
private
def language
'pebblekit_android'
end
def process_summary(zipfile, summary)
summary.css('tbody tr').each do | row |
name = row.at_css('td.colFirst').content
package = {
name: name,
url: "#{@path}#{name_to_url(name)}/",
children: [],
methods: [],
enums: [],
exceptions: [],
path: [name]
}
add_symbol(name: name, url: "#{@path}#{name_to_url(name)}/")
@tree << package
end
@tree.each do | package |
entry = zipfile.glob("javadoc/#{name_to_url(package[:name])}/package-summary.html").first
summary = Nokogiri::HTML(entry.get_input_stream.read)
process_package(zipfile, package, summary)
end
end
def process_package(zipfile, package, summary)
url = "#{@path}#{name_to_url(package[:name])}"
html = summary.at_css('.contentContainer').to_html
html = process_html(html, url)
@pages << PageDocPebbleKitAndroid.new(@site, @site.source, url, package[:name], html, package)
class_table = summary.css('table[summary~="Class Summary"]')
class_table.css('tbody tr').each do | row |
name = row.at_css('td.colFirst').content
package[:children] << {
name: name,
summary: row.at_css('.colLast').content,
url: "#{url}/#{name}",
path: package[:path].clone << name,
type: 'class',
children: [],
methods: [],
enums: [],
exceptions: []
}
add_symbol(name: "#{package[:name]}.#{name}", url: "#{url}/#{name}")
end
enum_table = summary.css('table[summary~="Enum Summary"]')
enum_table.css('tbody tr').each do | row |
name = row.at_css('.colFirst').content
package[:children] << {
name: name,
summary: row.at_css('.colLast').content,
path: package[:path].clone << name,
url: "#{url}/#{name}",
type: 'enum',
children: [],
methods: [],
enums: [],
exceptions: []
}
add_symbol(name: "#{package[:name]}.#{name}", url: "#{url}/#{name}")
end
summary.css('table[summary~="Exception Summary"]').css('tbody tr').each do | row |
name = row.at_css('td.colFirst').content
package[:children] << {
name: name,
summary: row.at_css('.colLast').content,
path: package[:path].clone << name,
url: "#{url}/#{name}",
type: 'exception',
children: [],
methods: [],
enums: [],
exceptions: []
}
add_symbol(name: "#{package[:name]}.#{name}", url: "#{url}/#{name}")
end
package[:children].each do | child |
filename = "javadoc/#{name_to_url(package[:name])}/#{child[:name]}.html"
child_url = '/docs/pebblekit-android/' + package[:name].split('.').join('/') + '/' + child[:name] + '/'
entry = zipfile.glob(filename).first
summary = Nokogiri::HTML(entry.get_input_stream.read)
method_table = summary.css('table[summary~="Method Summary"]')
method_table.css('tr').each do | row |
next unless row.at_css('.memberNameLink')
name = row.at_css('.memberNameLink').content
child[:methods] << {
name: name,
summary: row.at_css('.block') ? row.at_css('.block').content : '',
url: child_url + '#' + name,
type: 'method'
}
add_symbol(name: [package[:name], child[:name], name].join('.'), url: child_url + '#' + name)
end
html = summary.at_css('.contentContainer').to_html
html = process_html(html, child_url)
@pages << PageDocPebbleKitAndroid.new(@site, @site.source, child_url, child[:name], html, child)
end
end
def name_to_url(name)
name.split('.').join('/')
end
def process_html(html, root)
contents = Nokogiri::HTML(html)
contents.css('a').each do | link |
next if link['href'].nil?
href = File.expand_path(link['href'], root)
href = href.sub('/com/com/', '/com/')
href = href.sub('.html', '/')
link['href'] = href
end
contents.css('.memberSummary caption').remove
contents.to_html
end
end
class PageDocPebbleKitAndroid < Jekyll::Page
def initialize(site, base, dir, title, contents, group)
@site = site
@base = base
@dir = dir
@name = 'index.html'
@contents = contents
@group = group
process(@name)
read_yaml(File.join(base, '_layouts', 'docs'), 'pebblekit-android.html')
data['title'] = title.to_s
end
def to_liquid(attrs = ATTRIBUTES_FOR_LIQUID)
super(attrs + %w(
contents
group
))
end
attr_reader :contents
def group
if @group.nil?
{}
else
JSON.parse(JSON.dump(@group))
end
end
end
end

View File

@@ -1,240 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'zip'
require 'nokogiri'
require 'slugize'
require 'open-uri'
module Pebble
# PebbleKit iOS documentation processing class.
class DocumentationPebbleKitIos < Documentation
def initialize(site, source, root)
super(site)
@site = site
@url_root = root
open(source) do |zf|
Zip::File.open(zf.path) do |zipfile|
zipfile.each { |entry| process_entry(entry) }
end
end
end
private
def language
'pebblekit_ios'
end
def process_entry(entry)
return unless File.extname(entry.name) == '.html'
doc = Nokogiri::HTML(entry.get_input_stream.read)
process_index(doc) if File.basename(entry.name) == 'index.html'
process_normal_entry(doc, entry)
end
def process_normal_entry(doc, entry)
doc_entry = DocEntryPebbleKitIos.new(entry, doc, @url_root)
add_symbol(doc_entry.to_symbol)
doc_entry.anchor_symbols.map { |symbol| add_symbol(symbol) }
@pages << doc_entry.create_page(@site)
end
def process_index(doc)
headers = doc.at_css('#content').css('h2').map(&:content)
lists = doc.at_css('#content').css('ul').map { | list | list.css('li') }
headers.each_with_index do |header, index|
process_index_header(header, index, lists)
end
end
def process_index_header(header, index, lists)
tree_item = {
name: header,
url: "#{@url_root}##{header.slugize}",
children: []
}
lists[index].each { |item| process_index_header_item(tree_item, item) }
@tree << tree_item
end
def process_index_header_item(tree_item, item)
tree_item[:children] << {
name: item.content,
url: "#{@url_root}#{item.at_css('a')['href'].sub('.html', '/').gsub('+', '%2B')}",
path: [item.content],
children: []
}
end
end
# DocEntryIos is an iOS documentation class used to process a single page
# of the iOS documentation.
class DocEntryPebbleKitIos
def initialize(entry, doc, url_root)
@entry = entry
@doc = doc
@url_root = url_root
end
def to_symbol
{ name: name, url: url.gsub('+', '%2B') }
end
def anchor_symbols
@doc.css('a[name^="//api"][title]').map do |anchor|
anchor_to_symbol(anchor)
end
end
def create_page(site)
return nil if @doc.at_css('#content').nil?
contents = @doc.at_css('#content')
title = @doc.at_css('.title').content
group = { 'path' => [File.basename(path)] }
PageDocPebbleKitIos.new(site, url, title, contents, group)
end
private
def name
File.basename(@entry.name).sub('.html', '')
end
def url
@url_root + path
end
def path
@entry.name.sub('.html', '/')
end
def anchor_to_symbol(anchor)
summary = @doc.at_css("a[name=\"#{anchor['name']}\"] + h3 + div")
{
name: anchor['title'],
url: (url + '#' + anchor['name']).gsub('+', '%2B'),
summary: summary.content
}
end
end
# Jekyll Page subclass for rendering the iOS documentation pages.
class PageDocPebbleKitIos < Jekyll::Page
attr_reader :group
def initialize(site, dir, title, contents, group)
@site = site
@base = site.source
@dir = dir
@name = 'index.html'
@contents = contents
@group = group
process(@name)
process_contents
read_yaml(File.join(@base, '_layouts', 'docs'), 'pebblekit-ios.html')
data['title'] = title
end
def to_liquid(attrs = ATTRIBUTES_FOR_LIQUID)
super(attrs + %w(
contents
group
))
end
def contents
@contents.to_html
end
private
def process_contents
# Clean up links
@contents.css('a').each { |link| process_page_link(link) }
remove_duplicated_title
switch_specification_section_table_headers_to_normal_cells
clean_up_method_titles
switch_parameter_tables_into_definition_lists
remove_footer
end
def process_page_link(link)
process_page_link_class(link) unless link['name'].nil?
process_page_link_href(link) unless link['href'].nil?
end
def process_page_link_class(link)
link['class'] = '' if link['class'].nil?
link['class'] << ' anchor'
end
def process_page_link_href(link)
link['href'] = link['href'].gsub('../', '../../')
link['href'] = link['href'].gsub('.html', '/')
link['href'] = link['href'].gsub('+', '%2B')
end
def remove_duplicated_title
@contents.css('h1').each(&:remove)
end
def switch_specification_section_table_headers_to_normal_cells
@contents.css('.section-specification th').each do |n|
n.node_name = 'td'
n['class'] = 'specification-title'
end
end
def clean_up_method_titles
# Remove the <code><a> tags inside h3.method-title nodes, strip nbsp and
# add the subsubtitle class.
@contents.css('h3.method-title').each do |n|
method_title = n.at_css('code a')
n.content = method_title.content.gsub(/\A\u00A0+/, '') if method_title
n['class'] = 'subsubtitle method-title'
end
end
def switch_parameter_tables_into_definition_lists
# Change the table node into a definition list
# For each row recover the parameter name and the description, and add
# them to the list as term and definition.
@contents.css('table.argument-def').each do |table|
table.node_name = 'dl'
parameters = table.css('tr').map do |row|
parameter = row.at_css('th.argument-name code')
parameter.node_name = 'em'
dt = Nokogiri::XML::Element.new('dt', table.document)
dt.add_child parameter
definition = row.at_css('td:not(.argument-name)').content
dd = Nokogiri::XML::Element.new('dd', table.document)
dd.children = definition
[dt, dd]
end.flatten(1)
table.children.unlink
parameters.each { |p| table.add_child p }
end
end
def remove_footer
@contents.css('footer').each(&:remove)
end
end
end

View File

@@ -1,140 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
module Pebble
class SearchMarkdown < Redcarpet::Render::HTML
def initialize()
@contents = Array.new
@sections = []
@section = {
:title => nil,
:contents => []
}
super()
end
def get_contents()
@contents.join(" \n ")
end
def get_sections()
unless @section.nil?
@sections << @section
end
@sections.map do | section |
section[:contents] = section[:contents].join("\n")
section
end
@sections
end
def block_code(code, language)
""
end
def header(text, header_level)
unless @section.nil?
@sections << @section
end
@section = {
:title => text,
:contents => []
}
@contents << text
""
end
def paragraph(text)
@contents << text
@section[:contents] << text
""
end
def codespan(text)
text
end
def image(link, title, alt_text)
""
end
def link(link, title, content)
content
end
def list(contents, type)
@contents << contents
@section[:contents] << contents
""
end
def list_item(text, list_type)
@contents << text
@section[:contents] << text
""
end
def autolink(link, link_type)
link
end
def double_emphasis(text)
text
end
def emphasis(text)
text
end
def linebreak()
""
end
def raw_html(raw_html)
""
end
def triple_emphasis(text)
text
end
def strikethrough(text)
text
end
def superscript(text)
text
end
def underline(text)
text
end
def highlight(text)
text
end
def quote(text)
text
end
def footnote_ref(number)
""
end
end
end

View File

@@ -1,81 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'redcarpet'
require 'nokogiri'
module Pebble
class TocGenerator
def initialize(max_depth=-1)
@max_depth = max_depth
@markdown = TocMarkdown.new()
@redcarpet = Redcarpet::Markdown.new(@markdown,
fenced_code_blocks: true,
autolink: true,
tables: true,
no_intra_emphasis: true,
strikethrough: true,
highlight: true)
end
def generate(content)
@redcarpet.render(content)
page_toc = @markdown.get_toc
toc_array(toc_normalised(page_toc))
end
private
# Convert the ToC array of hashes into an array of array so that it can
# be used in the Liquid template.
def toc_array(array)
array.map { |entry| [ entry[:id], entry[:title], entry[:level] ] }
end
# Normalised the ToC array by ensuring that the smallest level number is 1.
def toc_normalised(array)
min_level = 100
array.each { |entry| min_level = [ min_level, entry[:level] ].min }
level_offset = min_level - 1
array.map { |entry| entry[:level] -= level_offset; entry }.select do |entry|
@max_depth == -1 || entry[:level] <= @max_depth
end
end
end
class TocMarkdown < Redcarpet::Render::HTML
def initialize()
@toc = Array.new
@depth = 0
super()
end
def get_toc()
@toc
end
def header(text, header_level)
text = Nokogiri::HTML(text).text if text.include?('<')
entry = { title: text, id: text.slugize, level: header_level }
@toc << entry
""
end
end
end

View File

@@ -1,53 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Generates a list page for each blog author.
# The list of authors is in /source/_data/blog_authors.yml
module Jekyll
class AuthorPage < Page
def initialize(site, base, dir, author)
@site = site
@base = base
@dir = dir
@name = author[0] + '/index.html'
self.process(@name)
self.read_yaml(File.join(base, '_layouts'), 'blog/author_page.html')
self.data['posts'] = site.posts.docs.select { |post| post['author'] == author[0] }
self.data['author_name'] = author[1]['name']
self.data['author'] = author[0]
self.data['title'] = "Pebble Developer Blog: #{author[1]['name']}"
end
end
class AuthorPageGenerator < Generator
def generate(site)
if ! site.layouts.key? 'blog/author_page'
throw 'Layout for the blog author pages is missing.'
end
dir = site.config['tag_dir'] || 'blog/authors'
site.data['authors'].each do |author|
author[1]['num_posts'] = site.posts.docs.select { |post| post['author'] == author[0] }.length
site.pages << AuthorPage.new(site, site.source, dir, author)
end
end
end
end

View File

@@ -1,69 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Generates a list page for each blog tag.
require 'slugize'
module Jekyll
class TagPage < Page
def initialize(site, base, dir, tag)
@site = site
@base = base
@dir = dir
@name = tag[0].slugize + '/index.html'
self.process(@name)
self.read_yaml(File.join(base, '_layouts'), 'blog/tag_page.html')
self.data['posts'] = tag[1].sort_by(&:date).reverse
self.data['name'] = tag[0]
self.data['tag'] = tag[0]
self.data['title'] = "Pebble Developer Blog: #{tag[0]}"
end
end
class TagPageRedirect < Page
def initialize(site, base, dir, tag)
@site = site
@base = base
@dir = dir
@name = tag[0].slugize + '.html'
self.process(@name)
self.read_yaml(File.join(base, '_layouts'), 'utils/redirect_permanent.html')
self.data['path'] = '/' + File.join(dir, tag[0].slugize) + '/'
end
end
class TagPageGenerator < Generator
def generate(site)
if ! site.layouts.key? 'blog/tag_page'
throw 'Layout for the blog tag pages is missing.'
end
dir = site.config['tag_dir'] || 'blog/tags'
site.tags.each do |tag|
site.pages << TagPage.new(site, site.source, dir, tag)
site.pages << TagPageRedirect.new(site, site.source, dir, tag)
end
end
end
end

View File

@@ -1,50 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
module Jekyll
class EnvironmentGenerator < Generator
priority :highest
def initialize(site)
# TODO: Figure out how to check for the environment type.
require 'dotenv'
Dotenv.load
end
def generate(site)
if !ENV.has_key?('URL') && ENV.has_key?('HEROKU_APP_NAME')
ENV['URL'] = "https://#{ENV['HEROKU_APP_NAME']}.herokuapp.com"
ENV['HTTPS_URL'] = "https://#{ENV['HEROKU_APP_NAME']}.herokuapp.com"
end
site.data['env'].each do |item|
if ENV.has_key?(item['env'])
set_config(site.config, item['config'], ENV[item['env']])
elsif item.has_key?('default')
set_config(site.config, item['config'], item['default'])
end
end
end
private
# TODO: Rewrite this function to allow for nested keys.
def set_config(config, key, value)
config[key] = value
end
end
end

View File

@@ -1,23 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# FilterAssetify is a Liquid filter to prepend the asset_path when needed
module FilterAssetify
def assetify(input)
asset_path = @context.registers[:site].config['asset_path']
%r{^/[^/]}.match(input) ? (asset_path + input) : input
end
end
Liquid::Template.register_filter(FilterAssetify)

View File

@@ -1,21 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
module FilterBasename
def basename(input, suffix)
File.basename(input, suffix)
end
end
Liquid::Template.register_filter(FilterBasename)

View File

@@ -1,28 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
module FilterFakePlatform
def fake_platform(input)
case input
when 'aplite'
'SDK 3'
when 'basalt'
'SDK 4'
else
'??'
end
end
end
Liquid::Template.register_filter(FilterFakePlatform)

View File

@@ -1,29 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
module FilterHashSort
def hash_sort(hash, property=nil)
return [] if hash.nil?
sorted_hash = []
hash.each { |key, value| sorted_hash << [key, value] }
if property.nil?
sorted_hash.sort! { |a, b| a[0] <=> b[0] }
else
sorted_hash.sort! { |a, b| a[1][property] <=> b[1][property] }
end
sorted_hash
end
end
Liquid::Template.register_filter(FilterHashSort)

View File

@@ -1,28 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Liquid filter that does magic to make plurals easy.
module Pluralize
def pluralize(number, singular, plural = nil)
if number == 1
"#{number} #{singular}"
elsif plural.nil?
"#{number} #{singular}s"
else
"#{number} #{plural}"
end
end
end
Liquid::Template.register_filter(Pluralize)

View File

@@ -1,25 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'slugize'
# Liquid filter that turns a string into a slug.
# Used to turn tag names into the tag URL part.
module FilterSlugize
def slugize(input)
input.slugize
end
end
Liquid::Template.register_filter(FilterSlugize)

View File

@@ -1,236 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'htmlentities'
require 'algoliasearch'
require 'slugize'
require 'dotenv'
require 'securerandom'
module Jekyll
class GeneratorAlgolia < Generator
# Do this last so everything else has been processed already.
priority :lowest
def initialize(_config)
Dotenv.load
end
def generate(site)
@site = site
return unless check_config?
@prefix = site.config['algolia_prefix'] || ''
@random_code = random_code
Algolia.init(application_id: site.config['algolia_app_id'],
api_key: site.config['algolia_api_key'])
@indexes = setup_indexes
generate_all
end
private
def check_config?
if @site.config['algolia_app_id'].nil? || @site.config['algolia_app_id'].empty?
Jekyll.logger.warn(
'Config Warning:',
'You did not provide a ALGOLIA_APP_ID environment variable.'
)
return false
end
if @site.config['algolia_api_key'].nil? || @site.config['algolia_api_key'].empty?
Jekyll.logger.warn(
'Config Warning:',
'You did not provide a ALGOLIA_API_KEY environment variable.'
)
return false
end
true
end
def generate_all
generate_blog_posts
generate_guides
generate_documentation
generate_none_guide_guides
generate_other
end
def random_code
SecureRandom.hex
end
def setup_indexes
indexes = {}
@site.data['search_indexes'].each do |name, properties|
index = Algolia::Index.new(@prefix + name)
unless properties['settings'].nil?
index.set_settings(properties['settings'])
end
indexes[name] = index
end
indexes
end
def generate_documentation
return if @site.data['docs'].nil?
documents = @site.data['docs'][:symbols].map do |item|
next if item[:language] == 'c_preview'
if item[:summary].nil? || item[:summary].strip.length == 0
Jekyll.logger.warn(
'Search Warning:',
"There was no summary for the symbol '#{item[:name]}' in #{item[:language]}."
)
end
{
'objectID' => item[:url],
'title' => item[:name],
'splitTitle' => item[:name].split(/(?=[A-Z])/).join(' '),
'url' => item[:url],
'summary' => item[:summary],
'kind' => item[:kind],
'language' => item[:language],
'type' => 'documentation',
'ranking' => doc_language_rank[item[:language]] * 1000,
'randomCode' => @random_code
}
end.compact
@indexes['documentation'].save_objects(documents)
end
def generate_blog_posts
documents = []
@site.posts.docs.each do | post |
# Calculate the age of the post so we can prioritise newer posts
# over older ones.
# NOTE: post.date is actually a Time object, despite its name
age = (Time.now - post.date).round
author = post.data['author']
post.get_sections.each do | section |
# Ignore sections without any contents.
if section[:contents].strip.size == 0
next
end
if section[:title].nil?
url = post.url
else
url = post.url + '#' + section[:title].slugize
end
document = {
'objectID' => url,
'title' => post.data['title'],
'sectionTitle' => section[:title],
'url' => url,
'urlDisplay' => post.url,
'author' => author,
'content' => HTMLEntities.new.decode(section[:contents]),
'posted' => post.date,
'age' => age,
'type' => 'blog post',
'randomCode' => @random_code
}
documents << document
end
end
@indexes['blog-posts'].save_objects(documents)
end
def generate_guides
documents = []
return if @site.collections['guides'].nil?
@site.collections['guides'].docs.each do | guide |
group = @site.data['guides'][guide.data['guide_group']]
unless group.nil? || group['subgroups'].nil? || guide.data['guide_subgroup'].nil?
subgroup = group.nil? ? '' : group['subgroups'][guide.data['guide_subgroup']]
end
guide.get_sections.each do | section |
url = guide.url
unless section[:title].nil?
url = url + '#' + section[:title].slugize
end
document = {
'objectID' => url,
'title' => guide.data['title'],
'sectionTitle' => section[:title],
'url' => url,
'urlDisplay' => guide.url,
'content' => HTMLEntities.new.decode(section[:contents]),
'group' => group.nil? ? '' : group['title'],
'subgroup' => subgroup.nil? ? '' : subgroup['title'],
'type' => 'guide',
'randomCode' => @random_code
}
documents << document
end
end
@indexes['guides'].save_objects(documents)
end
def generate_none_guide_guides
documents = []
gs_pages = @site.pages.select { |page| page.data['search_index'] }
gs_pages.each do |page|
page.get_sections.each do |section|
url = page.url
url = url + '#' + section[:title].slugize unless section[:title].nil?
document = {
'objectID' => url,
'title' => page.data['title'],
'sectionTitle' => section[:title],
'url' => url,
'urlDisplay' => page.url,
'content' => HTMLEntities.new.decode(section[:contents]),
'group' => page.data['search_group'],
'subgroup' => page.data['sub_group'],
'type' => 'not-guide',
'randomCode' => @random_code
}
documents << document
end
end
@indexes['guides'].save_objects(documents)
end
def generate_other
documents = @site.data['search-other'].map do |other|
{
'objectID' => other['id'],
'title' => other['title'],
'url' => other['url'],
'content' => other['description'],
'randomCode' => @random_code
}
end
@indexes['other'].save_objects(documents)
end
def doc_language_rank
{
'c' => 10,
'rockyjs' => 9,
'pebblekit_js' => 8,
'pebblekit_android' => 6,
'pebblekit_ios' => 4
}
end
end
end

View File

@@ -1,166 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'open-uri'
require 'zip'
require 'nokogiri'
require_relative '../lib/pebble_documentation_pebblekit_android.rb'
require_relative '../lib/pebble_documentation_c.rb'
require_relative '../lib/pebble_documentation_js.rb'
require_relative '../lib/pebble_documentation_pebblekit_ios.rb'
require_relative '../lib/toc_generator.rb'
OpenURI::Buffer.send :remove_const, 'StringMax' if OpenURI::Buffer.const_defined?('StringMax')
OpenURI::Buffer.const_set 'StringMax', 0
# Master plugins for processing the documentation on the site.
# The actual work is done in individual classes for each language type.
# Each class generates three types of data:
# - Symbols
# - Pages
# - Tree
#
# The Symbols are a list of objects that are things such as methods, classes
# or enums, that are used to populate the search indexes, and power the double
# backtick docs linking.
#
# The Pages are the Jekyll pages that will be part of the built site and are
# what the user will see.
#
# The Tree is used to build the site navigation.
#
# Note: The docs_url variable is created from the environment.
# See environment.md for more information.
module Jekyll
class DocsGenerator < Generator
priority :high
def generate(site)
@site = site
@docs = {
symbols: [],
pages: [],
tree: {}
}
if @site.config['docs_url'].nil? || @site.config['docs_url'].empty?
Jekyll.logger.warn(
'Config Warning:',
'You did not provide a DOCS_URL environment variable.'
)
elsif !@site.config['skip_docs'].nil? && (@site.config['skip_docs'] == 'true')
Jekyll.logger.info('Docs Generation:', 'Skipping documentation generation...')
else
Jekyll.logger.info('Docs Generation:', 'Generating pages...')
generate_docs
render_pages
Jekyll.logger.info('Docs Generation:', 'Done.')
end
set_data
end
private
def generate_docs
# The order of these functions will determine the order of preference
# when looking up symbols e.g. double backticks
# DO NOT CHANGE THE ORDER UNLESS YOU KNOW WHAT YOU ARE DOING
generate_docs_c
generate_docs_c_preview unless @site.data['docs']['c_preview'].nil?
generate_docs_rocky_js
generate_docs_pebblekit_js
generate_docs_pebblekit_android
generate_docs_pebblekit_ios
end
def render_pages
@docs[:pages].each { |page| @site.pages << page }
end
def set_data
# A somewhat ugly hack to let the Markdown parser have access
# to this data.
@site.config[:docs] = @docs
@site.data['docs'] = @docs
# Another ugly hack to make accessing the data much easier from Liquid.
@site.data['docs_tree'] = JSON.parse(JSON.dump(@docs[:tree]))
@site.data['symbols'] = JSON.parse(JSON.dump(@docs[:symbols]))
end
def generate_docs_c
docs = Pebble::DocumentationC.new(
@site,
@site.config['docs_url'] + @site.data['docs']['c'],
'/docs/c/'
)
load_data(docs, :c)
end
def generate_docs_c_preview
docs = Pebble::DocumentationC.new(
@site,
@site.config['docs_url'] + @site.data['docs']['c_preview'],
'/docs/c/preview/',
'c_preview'
)
load_data(docs, :c_preview)
end
def generate_docs_rocky_js
docs = Pebble::DocumentationJs.new(
@site,
@site.data['docs']['rocky_js'],
'/docs/rockyjs/',
'rockyjs',
true
)
load_data(docs, :rockyjs)
end
def generate_docs_pebblekit_js
docs = Pebble::DocumentationJs.new(
@site,
@site.data['docs']['pebblekit_js'],
'/docs/pebblekit-js/',
'pebblekit_js'
)
load_data(docs, :pebblekit_js)
end
def generate_docs_pebblekit_android
docs = Pebble::DocumentationPebbleKitAndroid.new(
@site,
@site.config['docs_url'] + @site.data['docs']['pebblekit_android']
)
load_data(docs, :pebblekit_android)
end
def generate_docs_pebblekit_ios
docs = Pebble::DocumentationPebbleKitIos.new(
@site,
@site.config['docs_url'] + @site.data['docs']['pebblekit_ios'],
'/docs/pebblekit-ios/'
)
load_data(docs, :pebblekit_ios)
end
def load_data(docs, type)
@docs[:tree][type] = []
docs.load_symbols(@docs[:symbols])
docs.create_pages(@docs[:pages])
docs.build_tree(@docs[:tree][type])
end
end
end

View File

@@ -1,65 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
module Jekyll
class GeneratorExamples < Generator
def initialize(_config)
end
def generate(site)
@site = site
process_tags
process_languages
process_hardware_platforms
@site.data['examples_metadata'] = {
'tags' => @tags,
'languages' => @languages,
'hardware_platforms' => @hardware_platforms
}
end
def process_tags
@tags = {}
@site.data['examples'].each do |example|
next if example['tags'].nil?
example['tags'].each do |tag|
@tags[tag] = { 'count' => 0 } unless @tags.has_key?(tag)
@tags[tag]['count'] += 1
end
end
end
def process_languages
@languages = {}
@site.data['examples'].each do |example|
next if example['languages'].nil?
example['languages'].each do |language|
@languages[language] = { 'count' => 0 } unless @languages.has_key?(language)
@languages[language]['count'] += 1
end
end
end
def process_hardware_platforms
@hardware_platforms = {}
@site.data['examples'].each do |example|
next if example['hardware_platforms'].nil?
example['hardware_platforms'].each do |hw|
@hardware_platforms[hw] = { 'count' => 0 } unless @hardware_platforms.has_key?(hw)
@hardware_platforms[hw]['count'] += 1
end
end
end
end
end

View File

@@ -1,94 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'htmlentities'
require 'algoliasearch'
require 'slugize'
require 'dotenv'
module Jekyll
class GeneratorGuides < Generator
priority :highest
def initialize(config)
end
def generate(site)
@site = site
site.collections['guides'].docs.each do |guide|
group = find_group(guide)
subgroup = find_subgroup(guide, group)
guide.data['group_data'] = group
guide.data['subgroup_data'] = subgroup
unless subgroup.nil?
subgroup['guides'] << {
'title' => guide.data['title'],
'url' => guide.url,
'menu' => guide.data['menu'],
'order' => guide.data['order'],
'summary' => guide.data['description']
}
else
unless group.nil?
group['guides'] << {
'title' => guide.data['title'],
'url' => guide.url,
'menu' => guide.data['menu'],
'order' => guide.data['order'],
'summary' => guide.data['description']
}
end
end
end
site.data['guides'] = [] if site.data['guides'].nil?
site.data['guides'].each do |id, group|
group['url'] = "/guides/#{id}/"
if group['subgroups'].nil?
group['subgroups'] = []
next
end
group['subgroups'].each do |id, subgroup|
subgroup['url'] = "#{group['url']}#{id}/"
end
end
end
def find_group(guide)
@site.data['guides'].each do |id, group|
if id == guide.data['guide_group']
group['guides'] = [] if group['guides'].nil?
return group
end
end
nil
end
def find_subgroup(guide, group)
return if group.nil? || group['subgroups'].nil?
group['subgroups'].each do |id, subgroup|
if id == guide.data['guide_subgroup']
subgroup['guides'] = [] if subgroup['guides'].nil?
return subgroup
end
end
nil
end
end
end

View File

@@ -1,35 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'googlestaticmap'
module Jekyll
class GeneratorMeetups < Generator
def initialize(config)
end
def generate(site)
@site = site
map = GoogleStaticMap.new(:width => 700, :height => 500)
site.data['meetups'].each do |meetup|
map.markers << MapMarker.new(:color => "0x9D49D5FF",
:location => MapLocation.new(:latitude => meetup['pin']['latitude'],
:longitude => meetup['pin']['longitude']
)
)
end
@site.data['meetups_map_url'] = map.url(:auto)
end
end
end

View File

@@ -1,58 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'uglifier'
require 'digest'
module Jekyll
# Jekyll Generator for concatenating and minifying JS for production site
class GeneratorMinifyJS < Generator
priority :highest
def initialize(_)
end
def generate(site)
return if site.config['rack_env'] == 'development'
@site = site
@tmp_dir = File.join(site.source, '../tmp/')
@js_dir = 'assets/js/'
@tmp_js_dir = File.join(@tmp_dir, @js_dir)
libs_js = uglify_libs
libs_md5 = Digest::MD5.hexdigest(libs_js)
@site.data['js']['lib_hash'] = libs_md5
create_libs_js(libs_js, libs_md5)
end
private
def uglify_libs
ugly_libs = []
@site.data['js']['libs'].each do |lib|
lib_path = File.join(@site.source, 'assets', lib['path'])
ugly_libs << Uglifier.compile(File.read(lib_path))
end
ugly_libs.join("\n\n")
end
def create_libs_js(js, md5)
FileUtils.mkdir_p(@tmp_js_dir)
File.open(File.join(@tmp_js_dir, "libs-#{md5}.js"), 'w') do |f|
f.write(js)
end
@site.static_files << Jekyll::StaticFile.new(@site, @tmp_dir, @js_dir,
"libs-#{md5}.js")
end
end
end

View File

@@ -1,62 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
module Jekyll
class GeneratorRedirects < Generator
priority :lowest
def initialize(config)
end
def generate(site)
@site = site
site.data['redirects'].each do |redirect|
if is_infinite_redirect?(redirect[0], redirect[1])
Jekyll.logger.warn "Redirect Warning:", "Skipping redirect of #{redirect[0]} to #{redirect[1]}"
next
end
@site.pages << RedirectPage.new(@site, @site.source, File.dirname(redirect[0]), File.basename(redirect[0]), redirect[1])
end
end
private
# Returns true if the redirect pair (from, to) will cause an infinite
# redirect.
def is_infinite_redirect?(from, to)
return true if from == to
return true if File.basename(from) == 'index.html' && File.dirname(from) == File.dirname(to + 'index.html')
false
end
end
class RedirectPage < Page
def initialize(site, base, dir, name, redirect_to)
@site = site
@base = base
@dir = dir
@name = name.empty? ? 'index.html' : name
self.process(@name)
self.read_yaml(File.join(base, '_layouts', 'utils'), 'redirect_permanent.html')
self.data['redirect_to'] = redirect_to
end
end
end

View File

@@ -1,54 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'redcarpet'
require_relative '../lib/search_markdown'
module Jekyll
module Convertible
def get_output
process_search
@search_markdown.get_contents
end
def get_sections
process_search
@search_markdown.get_sections
end
private
def process_search
unless @search_markdown.nil?
return
end
@search_markdown = Pebble::SearchMarkdown.new()
redcarpet = Redcarpet::Markdown.new(@search_markdown,
fenced_code_blocks: true,
autolink: true,
tables: true,
no_intra_emphasis: true,
strikethrough: true,
highlight: true)
payload = {}
info = { :filters => [Jekyll::Filters], :registers => { :site => site, :page => payload['page'] } }
raw_content = render_liquid(content, payload, info, '.')
redcarpet.render(raw_content)
end
end
end

View File

@@ -1,85 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require_relative '../lib/toc_generator'
module Jekyll
class Document
include Convertible
alias_method :parent_to_liquid, :to_liquid
def to_liquid
Utils.deep_merge_hashes parent_to_liquid, {
'toc' => toc,
'related_docs' => related_docs
}
end
private
def toc
unless @toc
generate_toc if data['generate_toc']
end
(@toc.nil? || @toc.empty?) ? nil : @toc
end
def related_docs
# Skip the warning, we don't want docs or links to them
if !@site.config['skip_docs'].nil? && (@site.config['skip_docs'] == 'true')
return
end
return nil if data['related_docs'].nil?
docs = data['related_docs'].map do | doc |
# Use existing doc data if it exists
if !doc.nil? and doc.is_a?(Hash) and doc.has_key?("name") and doc.has_key?("url")
doc
else
# use nil if data is formated in an unexpected way
if doc.nil? or !doc.is_a? String
next
else
# Otherwise search for the symbol
symbol = @site.config[:docs][:symbols].find do |symbol|
symbol[:name].downcase == doc.downcase
end
if symbol.nil?
Jekyll.logger.warn "Related Warning:", "Could not find symbol '#{doc}' in '#{data['title']}'"
next
else
{
'name' => symbol[:name],
'url' => symbol[:url],
}
end
end
end
end
end
def generate_toc
generator = Pebble::TocGenerator.new(data['toc_max_depth'] || -1)
@toc = generator.generate(content)
end
end
end

View File

@@ -1,45 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require_relative '../lib/toc_generator'
# Overriding the Jekyll Page class to do magic
module Jekyll
class Page
def to_liquid(attrs = ATTRIBUTES_FOR_LIQUID)
super(attrs + %w[
toc
])
end
private
def toc
unless @toc
generate_toc if data['generate_toc']
end
(@toc.nil? || @toc.empty?) ? nil : @toc
end
def generate_toc
generator = Pebble::TocGenerator.new(data['toc_max_depth'] || -1)
@toc = generator.generate(content)
end
end
end

View File

@@ -1,45 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require_relative '../lib/toc_generator'
# Overriding the Jekyll Page class to do magic
module Jekyll
class Post
def to_liquid(attrs = ATTRIBUTES_FOR_LIQUID)
super(attrs + %w[
toc
])
end
private
def toc
unless @toc
generate_toc
end
(@toc.nil? || @toc.empty?) ? nil : @toc
end
def generate_toc
generator = Pebble::TocGenerator.new(data['toc_max_depth'] || -1)
@toc = generator.generate(content)
end
end
end

View File

@@ -1,323 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'redcarpet'
require 'pygments'
require 'slugize'
require 'nokogiri'
module Jekyll
module Converters
# Jekyll Markdown Converter wrapper for Redcarpet using the PebbleMarkdown
# HTML render class.
class Markdown::PebbleMarkdownParser
def initialize(config)
@site_config = config
end
def convert(content)
content = '' if content.nil?
pbl_md = PebbleMarkdown.new(@site_config)
Redcarpet::Markdown.new(pbl_md,
fenced_code_blocks: true,
autolink: true,
tables: true,
no_intra_emphasis: true,
strikethrough: true,
highlight: true).render(content)
end
# Redcarpet HTML render class to handle the extra functionality.
class PebbleMarkdown < Redcarpet::Render::HTML
def initialize(config)
@site_config = config
super()
end
def preprocess(document)
process_links_with_double_backticks(document)
process_double_backticks(document)
document
end
# Add ID and anchors to all headers.
def header(text, header_level)
if text.include?('<')
id = Nokogiri::HTML(text).text.slugize
else
id = text.slugize
end
str = "<h#{header_level} id=\"#{id}\" class=\"anchor\">"
str += text
str += "</h#{header_level}>"
str
end
def paragraph(text)
if (match = /^\^(CP|LC)\^/.match(text))
"<p class=\"platform-specific\" data-sdk-platform=\"#{shortcode_to_platform(match[1])}\">#{text[(match[1].length + 2)..-1].strip}</p>"
else
"<p>#{text}</p>"
end
end
# Use Pygments to generate the syntax highlighting markup.
def block_code(code, language)
classes = ['highlight']
if /^nc\|/.match(language)
classes << 'no-copy'
language = language[3..-1]
end
if language == 'text'
"<div class=\"#{classes.join(' ')}\"><pre>#{code}</pre></div>"
else
set_classes(Pygments.highlight(code, lexer: language), classes)
end
end
def link(url, title, content)
if content == 'EMBED'
embed(url)
else
classes = []
if /^DOCS:/.match(title)
title = title[5..-1]
classes << 'link--docs'
end
# URL begins with a single slash (but not double slash)
url = baseurl + url if %r{^/[^/]}.match(url)
data_str = ''
if (match = regex_button.match(content))
classes << 'btn'
classes << 'btn--markdown'
classes.concat(match[3].split(',').map { |cls| 'btn--' + cls })
content = match[1]
end
if (match = regex_link_data.match(title))
match[3].split(',').each do |item|
item = item.split(':')
data_str += ' data-' + item[0] + '="' + item[1] + '"'
end
title = match[1]
end
"<a href=\"#{url}\"" \
" title=\"#{title}\"" \
" class=\"#{classes.join(' ')}\"#{data_str}>#{content}</a>"
end
end
# Better image handling.
# * Add size specificiations (taken from RDiscount)
# * Prepend the site baselink to images that beings with /
# TODO: Handle the cases where image link begins with //
# TODO: Maybe add additional style choices (centered, inline, etc)
def image(link, title, alt_text)
if (size_match = /^(.*)\ =([0-9]+)x?([0-9]*)$/.match(link))
link = size_match[1]
width = size_match[2]
height = size_match[3]
end
classes = []
if (match = regex_button.match(alt_text))
classes.concat(match[3].split(','))
alt_text = match[1]
end
link = asset_path + link if %r{^/[^/]}.match(link)
img_str = "<img src=\"#{link}\""
img_str += " title=\"#{title}\"" unless title.to_s.empty?
img_str += " alt=\"#{alt_text}\"" unless alt_text.to_s.empty?
img_str += " width=\"#{width}\"" unless width.to_s.empty?
img_str += " height=\"#{height}\"" unless height.to_s.empty?
img_str += " class=\"#{classes.join(' ')}\"" unless classes.empty?
img_str += ' />'
img_str
end
private
# This is used to process links that contain double backticks.
# For example:
# [click me](``Window``)
# This allows for the text of a link to be different than the name
# of the symbol you are linking to.
def process_links_with_double_backticks(document)
# Skip the warning, we don't want docs or links to them
if !@site_config['skip_docs'].nil? && (@site_config['skip_docs'] == 'true')
return
end
document.gsub!(/(\[([^\]]+)\])\(``([^`]+)``\)/) do |str|
url = Regexp.last_match[3]
text = Regexp.last_match[2]
text_in_brackets = Regexp.last_match[1]
language, symbol = parse_symbol(url)
entry = docs_lookup(symbol, language)
Jekyll.logger.warn('Backtick Warning:', "Could not find symbol '#{text}'") if entry.nil?
entry ? (text_in_brackets + "#{backtick_link(entry)}") : text
end
end
def process_double_backticks(document)
# Skip the warning, we don't want docs or links to them
if !@site_config['skip_docs'].nil? && (@site_config['skip_docs'] == 'true')
return
end
document.gsub!(/([^`]+|\A)``([^`]+)``/) do |str|
language, symbol = parse_symbol(Regexp.last_match[2])
entry = docs_lookup(symbol, language)
if entry.nil?
Jekyll.logger.warn('Backtick Warning:', "Could not find symbol '#{Regexp.last_match[2]}'")
language.nil? ? str : ('``' + Regexp.last_match[2][language.size+1..-1] + '``')
else
symbol_str = Regexp.last_match[2]
symbol_str = symbol_str[language.size+1..-1] unless language.nil?
"#{Regexp.last_match[1]}[`#{symbol_str}`]#{backtick_link(entry)}"
end
end
end
def backtick_link(symbol)
"(#{symbol[:url]} \"DOCS:#{symbol[:name]}\")"
end
# Split the documentation string into language and symbol name.
def parse_symbol(str)
match = /^([a-z]*:)?([A-Za-z0-9_:\.\ ]*)/.match(str)
language = match[1]
language = language[0..-2].downcase unless language.nil?
name = match[2]
return language, name
end
def docs_lookup(name, language)
return nil if name.nil?
@site_config[:docs][:symbols].find do |symbol|
symbol[:name].downcase == name.downcase &&
(language.nil? ? true : symbol[:language] == language)
end
end
def embed(url)
if (match = regex_youtube_video.match(url))
youtube(match[2])
elsif (match = regex_youtube_playlist.match(url))
youtube_playlist(match[3])
elsif (match = regex_vimeo_video.match(url))
vimeo(match[1])
elsif (match = regex_slideshare.match(url))
slideshare(match[1])
elsif (match = regex_gist.match(url))
gist(match[2])
end
end
def set_classes(html, classes)
doc = Nokogiri::HTML::DocumentFragment.parse(html)
doc.child['class'] = classes.join(' ')
doc.to_html
end
def youtube(id)
'<div class="embed embed--youtube"><div class="video-wrapper">' \
'<iframe width="640" height="360" frameborder="0" allowfullscreen' \
" src=\"//www.youtube.com/embed/#{id}?rel=0\" ></iframe>" \
'</div></div>'
end
def youtube_playlist(id)
'<div class="embed embed--youtube"><div class="video-wrapper">' \
'<iframe frameborder="0" allowfullscreen'\
" src=\"//www.youtube.com/embed/videoseries?list=#{id}\" ></iframe>" \
'</div></div>'
end
def vimeo(id)
'<div class="embed embed--vimeo"><div class="video-wrapper">' \
'<iframe width="500" height="281" frameborder="0"' \
' webkitallowfullscreen mozallowfullscreen allowfullscreen' \
" src=\"//player.vimeo.com/video/#{id}\"></iframe>" \
'</div></div>'
end
def slideshare(id)
'<div style="width: 100%; height: 0px; position: relative; padding-bottom: 63%;">' \
"<iframe src=\"https://www.slideshare.net/slideshow/embed_code/key/#{id}\"" \
' frameborder="0" allowfullscreen style="width: 100%; height: 100%; position: absolute;">' \
'</iframe>'\
'</div>'
end
def gist(id)
'<div class="embed embed--gist">' \
"<script src=\"//gist.github.com/#{id}.js\"></script>" \
'</div>'
end
def baseurl
@site_config['baseurl'] || ''
end
def asset_path
@site_config['asset_path'] || ''
end
def link_sdk(url, title, content)
end
def regex_youtube_video
%r{youtube\.com/(watch\?v=|v/|embed/)([a-z0-9A-Z\-_]*)}
end
def regex_youtube_playlist
%r{^(https?://)?([w]{3}\.)?youtube\.com/playlist\?list=([a-z0-9A-Z\-]*)}
end
def regex_vimeo_video
%r{vimeo.com/video/([0-9]+)}
end
def regex_slideshare
%r{slideshare.net/slideshow/embed_code/key/([a-z0-9A-Z]*)}
end
def regex_gist
%r{^(https?://)?gist.github\.com/(.*)}
end
def regex_button
/^(.*)\ (&gt;|>)\{?([a-z,0-9\-]*)\}?$/
end
def regex_link_data
/^(.*)\ (&gt;|>)\{([a-z\-_,:0-9A-Z]+)\}$/
end
def shortcode_to_platform(shortcode)
platforms = {
'CP' => 'cloudpebble',
'LC' => 'local'
}
platforms[shortcode]
end
end
end
end
end

View File

@@ -1,42 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
module Jekyll
class AlertBlock < Liquid::Block
alias_method :render_block, :render
def initialize(tag_name, text, tokens)
super
@type = text.strip
end
def render(context)
site = context.registers[:site]
converter = site.find_converter_instance(::Jekyll::Converters::Markdown)
content = converter.convert(render_block(context))
if @type == "important"
return "<div class=\"alert alert--fg-white alert--bg-dark-red\">" << "<strong>Important</strong><br/>" << "#{content}" << "</div>"
end
if @type == "notice"
return "<div class=\"alert alert--fg-white alert--bg-purple\">" << "<strong>Notice</strong><br/>" << "#{content}" << "</div>"
end
Jekyll.logger.error "Liquid Error:", "Alert type '#{@type}' is not valid. Use 'important' or 'notice'."
return ''
end
end
end
Liquid::Template.register_tag('alert', Jekyll::AlertBlock)

View File

@@ -1,31 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Liquid tag for including a style tag.
class TagAssetCss < Liquid::Tag
def initialize(tag_name, text, tokens)
super
@text = text
end
def render(context)
style = context[@text]
site = context.registers[:site]
unless %r{^//}.match(style)
style = "#{site.config['asset_path']}/css/#{style}.css"
end
"<link rel=\"stylesheet\" type=\"text/css\" href=\"#{style}\">"
end
end
Liquid::Template.register_tag('asset_css', TagAssetCss)

View File

@@ -1,31 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Liquid tag for including a script tag.
class TagAssetJs < Liquid::Tag
def initialize(tag_name, text, tokens)
super
@text = text
end
def render(context)
script = context[@text]
site = context.registers[:site]
unless %r{^//}.match(script)
script = "#{site.config['asset_path']}/js/#{script}.js"
end
"<script type=\"text/javascript\" src=\"#{script}\"></script>"
end
end
Liquid::Template.register_tag('asset_js', TagAssetJs)

View File

@@ -1,35 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Creates a link to a blog post author page and uses their full name when known.
class TagAuthorLink < Liquid::Tag
def initialize(tag_name, text, tokens)
super
@text = text
end
def render(context)
author_name = context[@text]
site = context.registers[:site]
author = site.data['authors'][author_name]
if author
url = "#{site.baseurl}/blog/authors/#{author_name}/"
"<a href=\"#{url}\">#{author['name']}</a>"
else
author_name
end
end
end
Liquid::Template.register_tag('author_link', TagAuthorLink)

View File

@@ -1,36 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
class TagAuthorPhoto < Liquid::Tag
def initialize(tag_name, text, tokens)
super
pieces = text.split(' ')
@name = pieces[0]
@size = pieces[1].to_i
end
def render(context)
author_name = context[@name]
site = context.registers[:site]
author = site.data['authors'][author_name]
unless author && author['photo']
author = site.data['authors']['pebble']
end
photo = author['photo']
photo = site.config['asset_path'] + photo if %r{^/[^/]}.match(photo)
"<img src=\"#{photo}\" width=#{@size} height=#{@size}>"
end
end
Liquid::Template.register_tag('author_photo', TagAuthorPhoto)

View File

@@ -1,58 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Liquid inline tag to produce an Edit Gist in CloudPebble button
class TagCloudPebbleEditGist < Liquid::Tag
def initialize(tag_name, gist_id, tokens)
super
@gist_id = gist_id.strip
end
def render(context)
page = context.registers[:page]
extension = File.extname(page['name'])
if extension == '.md'
render_markdown
else
render_html
end
end
def render_markdown
"[#{content} >{#{markdown_classes}}](#{url})"
end
def render_html
"<a href=\"#{url}\" title=\"\" class=\"#{html_classes}\">#{content}</a>"
end
private
def url
"https://cloudpebble.net/ide/gist/#{@gist_id}"
end
def html_classes
'btn btn--wide btn--pink'
end
def markdown_classes
'wide,pink'
end
def content
'Edit in CloudPebble'
end
end
Liquid::Template.register_tag('cloudpebble_edit_gist', TagCloudPebbleEditGist)

View File

@@ -1,43 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Liquid tag that displays the names of everyone who contributed on the file.
class TagGitContributors < Liquid::Tag
def initialize(tag_name, text, tokens)
super
@text = text
end
def render(context)
list = '<ul class="git-contributors">'
contributors(context).each do |name|
list += "<li>#{name}</li>" unless name.empty?
end
list += '</ul>'
list
end
private
def contributors(context)
site = context.registers[:site]
page = context[@text]
file_path = page['relative_path'] || page['path']
full_path = './' + site.config['source'] + file_path
names = `git log --follow --format='%aN |' "#{full_path}" | sort -u`
names.split('|').map { |name| name.strip }
end
end
Liquid::Template.register_tag('git_contributors', TagGitContributors)

View File

@@ -1,67 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
class TagGuideLink < Liquid::Tag
def initialize(tag_name, text, tokens)
super
@text = text.strip
end
def make_html(title, url)
return "<a href=\"#{url}\"><em>#{title}</em></a>"
end
def render(context)
guide_path = @text.split('#')[0].strip
guide_hash = (@text.split('#').length > 1 ? @text.split('#')[1] : '').strip
if guide_hash.length > 1
guide_hash = (guide_hash.split(' ')[0]).strip
end
# Custom title?
guide_title = nil
index = @text.index('"')
if index != nil
guide_title = (@text.split('"')[1]).strip
guide_title = guide_title.gsub('"', '')
guide_path = guide_path.split(' ')[0]
end
site = context.registers[:site]
site.collections['guides'].docs.each do |guide|
path = guide.relative_path.sub(/^_guides\//, '').sub(/\.md$/, '')
# Check if it's a 'section/guide' path
if path.index('/') != nil
if path == guide_path
return make_html(guide_title != nil ? guide_title : guide.data['title'],
"#{guide.url}#{guide_hash == '' ? '' : "##{guide_hash}"}")
end
end
# Check if it's a 'section' path
site.data['guides'].each do |id, group|
if id == guide_path
return make_html(guide_title != nil ? guide_title : group['title'], "/guides/#{guide_path}")
end
end
end
# No match
Jekyll.logger.error "Liquid Error:", "Could not find the guide or section for #{@text}."
return ''
end
end
Liquid::Template.register_tag('guide_link', TagGuideLink)

View File

@@ -1,35 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'pygments'
# Liquid block tag to run code through Pygments syntax highlighter.
class Highlight < Liquid::Block
def initialize(tag_name, markup, tokens)
super
options = JSON.parse(markup)
return unless options
@language = options['language']
@classes = options['classes']
@options = options['options'] || {}
end
def render(context)
str = Pygments.highlight(super.strip, lexer: @language, options: @options)
str.gsub!(/<div class="highlight"><pre>/,
"<div class=\"highlight #{@classes}\"><pre>")
str
end
end
Liquid::Template.register_tag('highlight', Highlight)

View File

@@ -1,38 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
class TagIfStartsWith < Liquid::Block
def initialize(tag_name, text, tokens)
super
matches = /^([A-Za-z\.\_\-\/]+) ([A-Za-z\.\_\-\/\']+)$/.match(text.strip)
@pieces = {
:outer => matches[1],
:inner => matches[2]
}
@text = text
end
def render(context)
outer = context[@pieces[:outer]]
inner = context[@pieces[:inner]]
if inner.nil? || outer.nil?
return ""
end
if outer.downcase.start_with?(inner.downcase)
return super.to_s.strip
end
""
end
end
Liquid::Template.register_tag('if_starts_with', TagIfStartsWith)

View File

@@ -1,30 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
class TagImportJs < Liquid::Tag
def initialize(tag_name, text, tokens)
super
@text = text
end
def render(context)
site = context.registers[:site]
filename = File.join(site.source, "_js", @text).strip
File.read(filename)
end
end
Liquid::Template.register_tag('import_js', TagImportJs)

View File

@@ -1,35 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
module Jekyll
class MarkdownBlock < Liquid::Block
alias_method :render_block, :render
def initialize(tag_name, markup, tokens)
super
end
# Uses the default Jekyll markdown parser to
# parse the contents of this block
#
def render(context)
site = context.registers[:site]
converter = site.find_converter_instance(::Jekyll::Converters::Markdown)
converter.convert(render_block(context))
end
end
end
Liquid::Template.register_tag('markdown', Jekyll::MarkdownBlock)

View File

@@ -1,39 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
module Jekyll
class PlatformBlock < Liquid::Block
alias_method :render_block, :render
def initialize(tag_name, text, tokens)
super
@platform = text.strip
end
def render(context)
if (@platform == "local") || (@platform == "cloudpebble")
site = context.registers[:site]
converter = site.find_converter_instance(::Jekyll::Converters::Markdown)
content = converter.convert(super)
return "<div class=\"platform-specific\" data-sdk-platform=\"#{@platform}\">#{content}</div>"
end
Jekyll.logger.error "Liquid Error:", "Platform '#{@platform}' is not valid. Use 'local' or 'cloudpebble'."
return ''
end
end
end
Liquid::Template.register_tag('platform', Jekyll::PlatformBlock)

View File

@@ -1,50 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'json'
class TagScreenshotViewer < Liquid::Block
def render(context)
site = context.registers[:site]
data = JSON.parse(super)
viewer_html = '<div class="screenshot-viewer">'
viewer_html += '<div class="screenshot-viewer__tabs js-screenshot-tabs">'
data['platforms'].each do |platform|
viewer_html += "<h4 data-platform=\"#{platform['hw']}\">#{platform['hw']}</h4>"
end
viewer_html += '</div>'
viewer_html += '<div class="screenshot-viewer__screenshots">'
data['platforms'].each do |platform|
viewer_html += "<div class=\"screenshot-viewer__platform\" data-platform=\"#{platform['hw']}\">"
image_url = make_image_url(data, platform)
viewer_html += "<img src=\"#{site.config['asset_path']}#{image_url}\" class=\"pebble-screenshot pebble-screenshot--#{platform['wrapper']}\" />"
viewer_html += '</div>'
end
viewer_html += '</div>'
viewer_html += '</div>'
viewer_html
end
private
def make_image_url(data, platform)
File.dirname(data['image']) + '/' + File.basename(data['image'], File.extname(data['image'])) +
"~#{platform['hw']}" + File.extname(data['image'])
end
end
Liquid::Template.register_tag('screenshot_viewer', TagScreenshotViewer)

View File

@@ -1,18 +0,0 @@
#!/bin/bash
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
documentation build ./js-docs/rocky -f json > source/_data/jsdocs-rocky.json
documentation build ./js-docs/pkjs -f json > source/_data/jsdocs-pkjs.json

View File

@@ -1,19 +0,0 @@
#!/bin/bash
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Updates the compiled Handlebars templates file from the source templates.
handlebars source/_js/templates/*.tpl -f source/assets/js/templates.js -e tpl

View File

@@ -1,33 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
SOURCE=$1;
DIR=$(dirname "$SOURCE")
FILENAME=$(basename "$SOURCE")
EXT="${FILENAME##*.}"
FILENAME="${FILENAME%.*}"
if [ -z "$1" ]
then
echo "\nUsage: $0 <MP4_FILE>\n"
exit 1;
fi
echo "Creating OGV file..."
ffmpeg -i $SOURCE -loglevel panic -q 5 -pix_fmt yuv420p -acodec libvorbis -vcodec libtheora $DIR/$FILENAME.ogv;
echo "Creating WEBM file..."
ffmpeg -i $SOURCE -loglevel panic -c:v libvpx -c:a libvorbis -pix_fmt yuv420p -quality good -b:v 2M -crf 5 -vf "scale=trunc(in_w/2)*2:trunc(in_h/2)*2" $DIR/$FILENAME.webm;
echo "Creating PNG poster..."
ffmpeg -i $SOURCE -loglevel panic -f image2 -ss 0 -vframes 1 $DIR/$FILENAME.png;
echo "Done!"

View File

@@ -1,51 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
layout: default
title: Oops! 404, Page not found
footer: true
error404: true
scripts:
- '404'
menu_section: none
---
<div class="row full-height" style="overflow: hidden;">
<div class="col-s-4 text-center hidden-xs hidden-s">
<img src="{{ site.asset_path }}/images/404-pebble.png" style="margin: -50% 50px 0;">
</div>
<div class="col-s-8">
<div class="container">
<div class="row">
<div class="col-l-12">
<h1 class="page-title">404 Page Not Found</h1>
<p>
Sorry, we couldn't find the page you were looking for.
</p>
<p>
If you clicked a link on the site and it led you here, we would
appreciate you <a href="/contact/?type=404">letting us know that we
broke something.</a>
</p>
<p id="js-404-search-intro" style="display: none;">
Below are some suggested pages that might be helpful in finding what
you were trying to find!
</p>
<ul id="js-404-search"></ul>
</div>
</div>
</div>
</div>
</div>

View File

@@ -1,42 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
permalink: /feed.xml
title: Pebble SDK 2.0 BETA0 - Changelog
date: 2013-11-01
---
This version is a preview of what will be publicly released soon as a BETA. This means that it is the last time we introduce large changes to the APIs, they will be much more stable in the future.
It includes some last significant changes that will impact every application.
* We have changed the format of the `wscript` file. **You must update your wscript file.** The easiest way to do this is to generate a new project with `pebble new-project` and use the generated `wscript`.
* Header files `pebble_os.h`, `pebble_app.h` and `pebble_fonts.h` are replaced by `pebble.h`
* `click_config_provider()` signature has changed and instead of filling a struct, you call `window_*_click_subscribe`. Please refer to the [Migration Guide](/guides/migration/).
* On AppMessage:
* We have changed the signature of most AppMessage functions. Please refer to the [Migration Guide](/guides/migration/).
* We have added functions to query the size of the AppMessage buffers. They still return the same value that in previous versions ... for now.
* We have added a [Mobile Developer Guide](/guides/communication/) covering PebbleKit iOS and Android. Please take a look at them, they should answer lots of questions.
* [PebbleKit Android Documentation](/guides/communication/using-pebblekit-android) is now available on the website and in the SDK `Documentation` folder.
* We have done a lot of work on PebbleKit JavaScript:
* The [documentation](/guides/communication/using-pebblekit-js) describes the new model for loading and stopping JavaScript apps. You should take a look.
* On Android only (for now) apps will automatically start when they get a message from Pebble.
* On Android only (for now) you can use the gear icon to open a configuration window on the phone.
* You can now call `Pebble.addEventListener` instead of `PebbleEventListener.addEventListener`
* DataLogging is now supported on Android, iOS6 and iOS7
* And of course we have fixed a large quantities of bugs.
This is a private release under NDA.

View File

@@ -1,74 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Pebble SDK 2.0 BETA1 - Changelog
date: 2013-11-06
---
* Pebble SDK 2.0 is currently in BETA and intended for developers only.
* SDK 2.0 will be released later this year as an over-the-air update to all Pebble users.
* Applications written for Pebble 1.x are not compatible with SDK 2.0
* ANCS Notifications (aka BLE notifications) are not supported for iOS users in this version
Updates:
* 2013 11 07: Added a firmware for watch with serial number starting with a 'Q' (aka hardware 1.5)
## What has changed since BETA0
### User Bug Fixes and Feature Enhancements
- Fixed crashing bugs on the iOS app. Users should experience improved stability.
- New iOS users no longer need to manage access to their address book in order to see Caller ID on their Pebble.
- The iOS app does not overflow the banner bar (at the top of the screen) on iOS7
- The Pebble now can show >80 unread notifications, up from 8 previously.
- Backlight is triggered on a tap from any of the 6 axes of the watch
- Android app stability has been improved
- On Android, switching orientation while updating firmware does not stop the firmware update
- The music app now stays open rather than switching back to the menu after 1 minute
### Known User Issues
- The status indication button in the main screen sometimes repeatedly throbs green then red, repeatedly.
- (iOS7 users, iPhone4S and higher) If you select "Enable Notifications" and select the Cancel button in the system alert that comes up, it can take up to 30 seconds for the iOS app to allow selection of "Enable Notifications" again. As a workaround, if you launched this screen from the Status screen, you can hit the up arrow, then the red "Not receiving notifications" button, and retry enabling notifications again.
- In certain conditions if you enable and disable Airplane mode on your Pebble, you may need to restart the Pebble iOS app completely in order to re-enable notifications again
- On Android, you may need to restart the Pebble app after installing a new version of a JavaScript app to ensure that your changes are successfully loaded.
- On Android, use of HTML5 local storage does not guarantee data will be saved across sessions.
- Duplicate APP_LOG messages can be received while using the pebble tool; these are intermittent and developers should use timestamps to identify duplicates
- If there is not enough app heap remaining, some essential functions that allocate on that heap will fail, such as system fonts or persistent storage
- The iOS app can sometimes crash when opening a PBW file if it is not already running
### Developer Bug Fixes and Enhancements (Major Feature Enhancements are covered in the SDK)
- Apps now only need one Pebble specific header, pebble.h
- Exiting an app showing no windows will now not crash the Pebble
- Pebble will not crash when cancelling an already cancelled timer
- Pebble will not crash when cancelling an unregistered timer
- Holding the up or down buttons now cause repeated clicks in menus
- Changed the default stroke color to Black instead of White, as the default background color is White
- Apps now cannot overwrite the system memory, and will be terminated if they attempt to
- Int type changes on many APIs to ensure future compatability
- User data can be attached to a window
- The pebble tool displays an error message if you try to install an application that is not compatible with the target firmware
- The menu icon resource is displayed even if it is not the first resource
- Libpebble times out if no apps are installed
- The valid range for UUIDs has changed - see the developer documentation
- The Android app now installs bundles in Gmail attachments
- System fonts now show capital W, Q and O
- `pebble Install`` will now install even if the Android app is left in the “Update” screen
- Apps will not crash if a text layer is not large enough to hold the requested text
- `pebble install --logs` proceeds to tail logs even when install fails
- Apps will not crash when popping/removing already popped/removed windows from the stack

View File

@@ -1,97 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Pebble SDK 2.0 BETA2 - Changelog
date: 2013-11-14
---
* Pebble SDK 2.0 is currently in BETA and intended for developers only.
* SDK 2.0 will be released later this year as an over-the-air update to all Pebble users.
* Applications written for Pebble 1.x are not compatible with SDK 2.0
## What has changed since BETA1
Overview:
- We have included ANCS in 2.0 - iOS users will get all notifications
- We have added a screenshot tool
- We have increased the AppMessage buffer size for PebbleKit JS Apps
- We have changed a few firmware APIs to always pass parameter in this order: (buffer, size)
- We have fixed many bugs
Known problems and bugs:
- We are still working actively on improving datalogging on iOS and Android. If you wish to use this framework, please get in touch with us and tell us about your experience.
- JavaScript apps on Android will only run if the phone is turned on and the Pebble app running (the easiest way to check this is to bring it to the foreground). This will be fixed soon.
- If you downloaded the SDK before 5pm PST on 2013-11-14, your API documentation is probably broken. We have fixed this and pushed a new release without updating the version number because there are absolutely no changes (except the doc is now there ;).
### Firmware
- Added support for ANCS
- Fix UI bug when getting phone calls
- Improved address book lookups when getting phone calls
- Changed the behaviour when an app is closed from PebbleKit: return to the last running app or watchface (instead of the launcher)
- Show malloc and free in the generated documentation
- Fix doc for AccelAxisType
- Do not animation a window disappearing if the window was pushed without animation
- Add `GCornersRight` in the documentation of `GCornerMask`
- Document `GTextOverflowMode`
- Document the return value of the `persist_*` functions
- Document `AppTimerCallback`
- When exiting an app, all unload handlers will be called for loaded windows
- Changed the order of parameters for `persist_read_data()`, `persist_read_string()`, `persist_write_data()`, `dict_calc_buffer_size()`, `dict_serialize_tuplets_to_buffer_with_iter()`: always ask for the pointer first and then the count or size
- Fix bug where the status bar would not be displayed properly
- Enabled Accelerometer high resolution output
- Automatically reset the accelerometer when app exits
- Removed the 1Hz accelerometer settings because it breaks the shake to backlight - Use peek() instead if you only need one sample per second.
- Updated the guaranteed minimum buffer sizes for appmessage. They are in fact 124 / 636.
- Fix bug where appLaunch commands would not be ACK'd
- Increased AppMessage buffer sizes for JavaScript apps: they get 2k in and out.
### iOS App
- Fixed several dataLogging bugs
- Fixed most common crashes reported by TestFlight
### Android App
- Fixed several dataLogging bugs
- Fixed most common crashes reported by TestFlight
### PebbleKit iOS
- DataLogging apps do not need to include an `appInfo.json` file anymore
- Use `setAppUUID` to give the UUID of the app you want to talk to
### PebbleKit Android
- Add `getWatchFWVersion()` to get a `FirmwareVersionInfo` object
- Add `isDataLoggingSupported`
### SDK Tools
- Added a `screenshot` command to the `pebble` tool
- Revert the change in the tool where we would enforce a specific range of uuids
- Improved error messages when the tools cannot be found
- Do not truncate log messages coming from the JavaScript console
- Only log app_log (and not system log) by default. Use `--verbose` to get all the logs.
### Examples
- Fix a bug in the dataspooling demo where sealions and pelicans got mixed up
- Fix PebbleKit Examples for the new `setAppUUID` style
- Fix examples to use the new parameter orders for `persist` functions

View File

@@ -1,117 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Pebble SDK 2.0 BETA3 - Changelog
date: 2013-12-12
---
* Pebble SDK 2.0 is currently in BETA and intended for developers only.
* SDK 2.0 will be released later this year as an over-the-air update to all Pebble users.
* Applications written for Pebble 1.x are not compatible with SDK 2.0
* If a 2.0 version of an application exists, the Pebble mobile applications will automatically install it when when a user upgrades her/his Pebble.
## What has changed since BETA2
Overview:
- The Android app fixes a large number of JS-related bugs.
- The Android app fixes a bug where all messages sent to android would be automatically acknowledged. Your application should acknowledge app messages.
- Some new user features in the firmware: Notification settings (with Do Not Disturb), better Alarms
- Lots of small UI and stability fixes in Pebble.
Known problems and bugs:
### Firmware
- added a Notification menu in the Settings to disable Notifications and configure a DoNotDisturb time frame
- much better Alarm app with a nicer UI, snooze support, disabled alarms support
- fix bugs where incoming calls could cause the vibration to stay on continuously
- fix a rare condition where the accelerometer would crash if an interrupt comes too late or the accelerometer sent 0 samples
- fix accelerometer behaviour when only 1 sample is requested: only send one sample (instead of 2)
- fix a bug where an iOS device could disconnect just 1-2 seconds after connecting
- automatically reconnect when user leaves Airplane Mode
- show (in settings) that vibrations are disabled when Pebble is plugged
- improved the set date/time UI to use the new DateTime UI (as in Alarms)
- adjust the framebuffer offset for modal window transitions
- reduced BLE connection interval
- log more information when an application crashes
- do not crash if an app_message section is re-opened - display warning instead
- fix a bug which caused firmware updates to fail under some conditions (mostly android)
- appsync will only update a dictionary if it has enough memory to do so (instead of finding out half-way that it does not have enough memory)
- always return to the launcher after an app crash (to avoid a crash loop on a watchface)
- *_destroy() will accept NULL pointers without errors
- always go back to the top of the menu when launching the menu from a watchface (to make "blind" navigation easier)
- fix a bug where an actionbar button would still be "pressed"
- show Bluetooth Name on getting started screen
- automatically delete old apps that are not compatible with this firmware version
- accelerate scrolling on the menu
- use modal window icon in the status bar as long as the modal window is displayed
- Export dict_size so external developers don't have to do pointer math :)
- fix a bug where scrolling in a long list of notifications could cause the display to "bounce"
- fix a bug where lots of app logging messages could overflow the system task queue and kill app message
- API documentation completely reviewed and updated
- missed call modal views will timeout after 180s
- force quit app when the back button is held for 2 seconds
- menu_cell_basic_draw() now automatically center the text in the cell. If you do not want a subtitle, pass NULL (otherwise, space will be reserved for the subtitle).
- fixed some bluetooth settings to avoid duplicated messages (could cause screenshot to go over 100%, duplicated log entries, firmware upgrade to fail, etc)
- `peek()`ing the accelerometer is not allowed anymore when you have also subscribed to receive updates
- fix a bug where the accelerometer would get stuck after a few hours
### iOS App
- fix a bug where datalogging could dump messages to another phone on your local network
- fix a bug where datalogging would get into a deadlock
- fix a bug where the developer connection would appear active but would be closed
### Android App
- fix a number of cases where a JS app would not be launched
- fix bug where clicking the configure icon would not open the configuration view of an app
- fix a bug which caused every AppMessage sent to Android to be acknowledged by the system
- Select the Google Play Music App as the default music player
- fix support email to use the Pebble bluetooth name instead of the last four digits of the serial
- if there is an error when uploading an app, do not dismiss the update screen right away
- do not dump large logs if stats json is not found
- check for firmware update when foregrounded
- fix bug where a canceled app install would be reported as completed
- fix bug where an install would fail silently because the resources could not be loaded
- display specific error message when a user tries to install a 2.0 app on a 1.x Pebble
- fix a bug where the android app would display error message "Could not update" while looking for updates in the background
### PebbleKit iOS
- allow one iOS application to exchange messages with several Pebble apps (with different UUIDs)
- fix a crash trying to parse invalid firmware version
- add CocoaPods support (see pebblekit-ios readme for more info)
- enabled "all warnings" and fixed errors
### PebbleKit Android
No changes.
### SDK Tools
- added support to upload any bundle (including firmware)
- added test to detect missing tools
- better implementation of the --debug flag
- fix bug where tools would fail when installed in a folder with a space in it
- fix bug where tools would fail on project with a space in the name
- some 1.x to 2.x conversion bugs fixed
- automatically re-enable applog when the watch reconnects
### Examples
- fix crashing bugs in 91Dub

View File

@@ -1,102 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Pebble SDK 2.0 BETA4 - Changelog
date: 2013-12-23
---
* Pebble SDK 2.0 is currently in BETA and intended for developers only.
* SDK 2.0 will be released early next year as an over-the-air update to all Pebble users.
* Applications written for Pebble 1.x are not compatible with SDK 2.0
* If a 2.0 version of an application exists, the Pebble mobile applications will automatically install it when when a user upgrades her/his Pebble.
**You can start uploading your application to the Pebble appstore TODAY - [Please do so](http://dev-portal.getpebble.com/)!**
## What has changed since BETA3
Overview:
- Fixed a problem where the iOS app would get killed after a few minutes in the background
- Lots of Data Logging fixes on the firmware and on Android
- Added timestamps on accelerometer samples
- Improved error handling for PebbleKit JS apps on iOS and Android
### Firmware
- Developers of apps can now register single and multi click handlers on the back button
- Holding down the back button for 1.5s will force quit an existing app
- Fixed bugs and optimize the filesystem: faster persist times, less problems with persistent storage, fix a bunch of rather complex problems where the recovery firmware could be damaged
- Fixed scroll offset bug when displaying notifications
- Dismiss missed call notfication after 180s
- Fixed a bug where unicode characters were not supported in appinfo.json
- Changed graphics_text_layout_get_max_used_size() to _not_ require a graphic context
- Fixed a few more bluetooth bugs
- Fixed a bug where Pebble could crash when you delete the last alarm
- Fixed memory read exception that can occur when using a malloc-ed appsync buffer
- Save notifications to storage during do not disturb
- Document AccelAxisType in API Documentation
- Fixed Music UI problems
- Automatically center on screen a selected cell in a SimpleMenuLayer
- Fixed bug where snprintf could crash the watch
- Display an error message if a 2.0 pebble is connected to a 1.x mobile app
- Fixed a bug where calling atoi() would crash an app
- Many DataLogging improvements and fixes based on new unit tests
- Display an alert on Pebble when we reset due to a system crash
- Ignore NULL pointer passed to text_layer_destroy()
- Limit the number of datalogging sessions to 20
- Fixed a race condition that occurs when you set the sampling rate immediately after subscribing to the accel service
- Keep persistent storage intact when upgrading an application
- Added timestamps on accelerometer samples and a flag indicating if the watch was vibrating at the time of the sample
- Fixed a bug where psleep could crash pebble
- Fixed a bug where text_layer could add ellipsis to the wrong line
### iOS App
- Fixed a bug where the iOS app would get killed in the background after just a few minutes
- Show a local notification if a developer is connected but the app is about to get killed
- PebbleKit JS: Fixed a bug where apps could not access localStorage with the array syntax
- PebbleKit JS: Fixed a bug where a space in an URL opened with XmlHTTPRequest could crash the iOS app
- PebbleKit JS: Fixed a bug where sending a byte array with 0xff in it would send 0x00 instead
### Android App
- PebbleKit JS: Fixed a bug where a byte array would not be sent properly for named keys
- Use new Android KitKat (4.4) APIs to do pairing on 4.4
- PebbleKit JS: Do not send ack for ack/nack messages
- Fixed Android crashing with OutOfMemory error when using Data Logging
- Fixed Android Data Logging of byte array that was not working
### PebbleKit iOS
- Do not ack ACKs...
### PebbleKit Android
- No changes
### SDK Tools
- Added support to libpebble to trigger reboot to recovery firmware
- Added support for computers where python2 and python3 co-exist
- Fixed an exception when receiving APP_LOG with extended characters
- Fixed a bug where unicode characters were not supported in characterRegex field of `appinfo.json`
- Fixed 30 second delay that can occur when building pebble apps on Ubuntu when there is no internet access
- Added Pillow python dependency: needed for the screenshot functionality
- Detect PIL/Pillow conflict and suggest a fix to the user
### Examples
- Added a License to the examples

View File

@@ -1,112 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Pebble SDK 2.0 BETA5 - Changelog
date: 2014-01-10
---
* Pebble SDK 2.0 is currently in BETA and intended for developers only.
* Applications written for Pebble 1.x are not compatible with SDK 2.0
* If a 2.0 version of an application exists, the Pebble mobile applications will automatically install it when when a user upgrades her/his Pebble.
**You can start uploading your application to the Pebble appstore TODAY - [Please do so](http://dev-portal.getpebble.com/)!**
## What has changed since BETA4
Overview:
- Fixed Android datalogging bugs where data would get duplicated
- Merged datalogging fixes for iOS that were supposed to be in BETA4 (sorry)
- Added an end of session message on Android datalogging
- Fixed accelerometer bugs where the accelerometer would stop sending data
- Changed the animation when switching from one watchface to the next ...
- Changed the battery API to return values going up to 100%
### Known Problems and limitations
* **Accelerometer locking up**: Although we have fixed several bugs around the accelerometer, we have noticed a few instance of the accelerometer locking up and the accel callback not being called anymore. If you see this happen again, please use the "Contact Support" button to send us logs. Make sure you change the subject to "Accelerometer lockup". Thank you very much!
* `getAccountToken()` (in PebbleKit JS) is not working yet. It currently returns a random string. In an upcoming update (before 2.0) it will return a unique token linked to the Pebble user account.
This is tied with appstore functionnalities and not available yet in this beta build.
* Some crash due to internal timers and deadlock conditions are still being investigated.
* This version will reset your persistent storage when you install it
### Changes for Firmware:
- Added a script in the SDK to help analyze app memory usage (analyze_static_memory_usage)
- Changed the animation between watchfaces
- Fix various composition bugs during animations
- Several fix to the Pebble filesystem to fix problems occuring in persistent storage and datalogging
- Add `bitmap_layer_get_bitmap()`
- s/1 minutes/1 minute/ in the alarm app
- Do not crash when loading a font from a NULL resource (can happen when memory is tight!)
- Ignore buttons while animating from one window to another
- Fix the back button in the getting started
- Fix simplicity to show the time immediately
- Fix sliding text to animate the time in immediately
- Change simplicity to load the fonts as system fonts
- Invert modal window status bar icons
- Reworked `gpath_draw_filled()` to use less memory and use heap instead of stack
- Improve persistent storage behaviour under tight memory
- Enforce file size limits
- Improve number of sectors of the filesystem
- Fix a bug where in some condition going up and down after installing a watchface would not return to it
- Fix a bug where `text_layer_get_content_size()` could return values that caused the text to be truncated
- Do not crash in `gpath_draw_filled()` if called with 0 points
- Added event service unsubscribe for app_focus_event (fixes a crash for Glance and Upright)
- Changed the battery API to return values going up to 100%
### Changes for Pebble iOS App:
- Fixes to datalogging to avoid duplicated data and iOS app getting stuck
### Changes for Pebble Android App:
- Added an intent sent when a data logging session is finished
- Fix a problem where JavaScript would not start on android 4.0
- Fix some bluetooth scanning bugs that could cause timeouts or pebbles not detected
- Improved bluetooth pairing screens for various Android versions
### Changes for PebbleKit iOS:
- Fix some threading/deadlock bugs
### Changes for PebbleKit Android:
- Do not retransmit same datalogging blocks more than once
- Add a callback when the datalogging session is finished
### Changes for SDK Tools:
- Added command `pebble analyze-size` to dump sections and symbol sizes
- Increase timeout of the wsclient (could be triggered when installing firmware)
- Added `--simple` option to `pebble new-project` to create a minimalist app
- Updated to websocket-client 1.12 and removed dependency to io_sock
### Changes for Examples:
- Update classio-battery-connection example to peek() the bluetooth connection status at startup
### Changes for Documentation:
- Updated JS configuration example
- Added link to the pebble-hacks/configurable project in the JS doc
- Removed reference to the 1Hz acc sampling rate (RIP)
- Added an example use of the `pebble install` command in the example page
- Updated the `app_focus_subscribe` documentation in the event guide
- Added a note in the datalogging guide to mention it's not a realtime system
- Added doc for `only_shown_on_communication` in the anatomy of a pebble app chapter
- Added that you can call `app_message_outbox_begin` in `outbox_sent` and `outbox_failed` now
- Fixed formatting of the appinfo.json example in the anatomy of a pebble app chapter

View File

@@ -1,92 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Pebble SDK 2.0 BETA6 - Changelog
date: 2014-01-17
---
* Pebble SDK 2.0 is currently in BETA and intended for developers only.
* Applications written for Pebble 1.x are not compatible with SDK 2.0
* If a 2.0 version of an application exists, the Pebble mobile applications will automatically install it when when a user upgrades her/his Pebble.
> **IMPORTANT NOTES FOR iOS Users**:
>
> * You must delete the Pebble app on your phone before installing this new version. It will now be called "Pebble Dev" and not "Pebble.". You must also re-install all of your JavaScript apps after installing this new version.
>
> * iPhone5S, iPad Air and Retina iPad Mini users will need to manually pair in the **Settings** of the phone.
## What has changed since BETA5
Overview:
- The iOS Application distributed with BETA6 includes the new Pebble appstore
- The firmware fixes a number of hard to reproduce crashes with system timers. This will fix a lot of the "Dangerously rebooting" Pebble crashes.
### Known Problems and limitations
* `getAccountToken()` (in PebbleKit JS) is not working yet. It currently returns a random string. In an upcoming update (before 2.0) it will return a unique token linked to the Pebble user account.
This is tied with appstore functionnalities and not available yet in this beta build.
* The bugs that were reported on datalogging-iOS on BETA5 are not fixed yet in this release
### Changes for Firmware:
* Rework the system timer to fix all timer related crashes
* Add support for Pebble Steel LED to show charging status
* Round rather than floor the battery charge percentage
* Reverted timings for stm32 for 64MHz system clock based on stable 16Hz SPI clock. Fixes display flicker at 30Hz, as well as saving power at the lower system clock (80->64) and sleeping more often due to faster display updates.
* Fix a crash when canceling the bluetooth pairing dialog
* Fix a bug where pushing a window in a window_unload callback would cause a crash
* Export AccelData structure in the API doc
* Vibrate when an app or watchface is installed
* Fix a bug where the phone modal window would not update properly
* Fix the light threshold for Pebble Steel
### Changes for Pebble iOS App:
* Added the Pebble appstore
* Added support for In-App Notifications
* Add support for migrating 1.x apps into 2.0 apps
* Fix a bug where the iOS app could crash when you switch away from a JavaScript app that has an ongoing network connection
* PebbleKit JS iOS: sendAppMessage() now returns a transaction id
### Changes for Pebble Android App:
* No changes.
### Changes for PebbleKit iOS:
* add isNewer convenience call to PBWatch+Version
* move NSJSONSerialization helper to PebbleVendor
* add isEqualVersionOnly to just compare version number components, ignoring timestamp & hash
### Changes for PebbleKit Android:
* No changes.
### Changes for SDK Tools:
* Fix spelling in an error message (s/Insure/Ensure/)
### Changes for Examples:
* No changes.
### Changes for Documentation:
* Fix a 404 on the pebble tool link in the JS guide
* Fix the persistence guide to reflect the new standardized parameters orders
* Fix a typo in the title of the UI framework guide
* Added designer resources in the UX design chapter

View File

@@ -1,145 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Pebble SDK 2.0 BETA7 - Changelog
date: 2014-01-23
---
Pebble SDK 2.0 is still in BETA and is **recommended only** for developers working on new applications for the upcoming Pebble appstore.
## Update Jan 31st: 2.0 Release Candidate 3
We fixed two more crashes. iOS user will automatically get the update. Android users can download it from this site.
Not sending an email to everyone this time because it really is a small changes and we want to spare your inbox before the week-end.
## Update Jan 30th: 2.0 Release Candidate 2
On January 30th, we released a 2.0 Release Candidate version of the firmware with the following changes:
* fixes a number of crashes
* app no longer gets killed when it cancels an invalid timer
* removes “persist_raw -9” message
* low battery message always uses the right icon
* fixes crash on watch shutdown
* fixes crash when using accel
## Updated Jan 29th: 2.0 Release Candidate
On January 29th, we released a 2.0 Release Candidate version of the firmware with the following changes:
* Fixed numerous crashes
* %Z flag passed to strftime no longer crashes the watch
* Fixed iOS connected but not receiving anything issue
* Firmware will now delete all data logging data on factory reset
* Rate limit logging to prevent apps from crashing app with logging loops
* Fixed issues were buttons become unresponsive
* Fixed gpath getting clipped in some cases
* Fixed accel lockup issue
* Fixed accel not using the right sampling rate
* Added low battery warning
* Cancel snooze timer when alarm is deleted
Please continue using BETA7 versions of the SDK and mobile applications.
## What has changed since BETA6
Overview:
- More random crashes fixed in the firmware
- Seriously improved datalogging on iOS (and some bugfixes on Android)
- Fixed the URL scheme to install Pebble applications. It did not work in Beta6.
- Added support for `getAccountToken()` in PebbleKit JS (iOS only at the moment)
- iOS application and PebbleKit iOS are now 64 bits compatible
- iOS application does not crash on iPhone 4 anymore
- Some breaking changes in PebbleKit iOS: We cannot use NSNumber categories in 64 bit because their size is unknown. We added a new PBNumber class. This class is returned if you use the NSNumber Pebble category.
### Known Problems and limitations
- Android does not include the Pebble appstore yet
- PebbleKit iOS apps may see error messages about parsing firmware in their logs. This will be removed soon and does not impact anything in PebbleKit iOS.
### Changes for Firmware:
- fix bugs with modal windows over fullscreen apps
- fix bugs where action bar buttons could get "stuck"
- reduced the power used by Pebble Steel LEDs
- fix some data logging corruption issues on Pebble
- fix a bug where the time of a notification would not be displayed properly
- adjusted the battery charged thresholds so that Pebble Steel turns green when apps show 100%
- fix a bug where you could get 110% battery
- fix a bug where datalogging session could be incompletely initialized when pushed
- fix a bug that could happen when looking for notifications
- fix a bug where some original Pebbles (ev2_4) would never hit 100% battery
- fix infinite loop if you push a modal while one is closing
- fix some button problems on Pebble Steel
### Changes for Pebble iOS App:
- added support for 64bits compilation
- fix a bug where 64 bit devices would not display the bluetooth accessory picker
- native login / signup screen
- fix some button sizes to display text properly
- calculate the area of the buttons on the left menu to highlight them dynamically
- data logging: do not print error messages for partially fetched data - unless we are actually done
- fix some bugs around the Bluetooth accessory picker
- better management of the screens stack in onboarding process. allows users to go back.
- do not display icon for watchfaces in the my pebble screen
- fix bug where appstore url-scheme would not work
- add link to terms and conditions
- deal with timeout errors while installing apps
- downloading apps in the Caches directory instead of Documents since that one gets pruned automatically by the system (Fixes pebblekit#39)
- only allow to start dragging the center view if you start dragging from the left edge
- fix crash for iPhone 4 users
- fix bug where datalogging would try to send data to the Pebble app (instead of 3rd party apps)
- lazy loading the web appstore views to improve loading speed
- sort apps alphabetically in the locker
- memory optimization to stay in the background longer
- getAccountToken() now working in JavaScript
- fix a bug where the configuration view was not sometimes not dismissed
- rename the "Done" button of the configuration view to "Cancel"
- send empty string back to the JS if the user cancels the configuration view (as per documentation)
- only show the "notifications not set up" if there's a watch connected
- fix a JS bug where in some conditions the 'showConfiguration' event might be fired before the 'ready' event
### Changes for Pebble Android App:
- Datalogging: if a session contains bad data, just remove it at startup
### Changes for PebbleKit iOS:
- PebbleKit iOS is now 64 bits (armv7s) compatible
- We cannot use NSNumber categories in 64 bit because their size is unknown. We added a new PBNumber class. This class is returned if you use the NSNumber Pebble category.
- Do not start the datalogging server if appUUID is all zeros
### Changes for PebbleKit Android:
No changes.
### Changes for SDK Tools:
No changes.
### Changes for Examples:
- Classio-battery-connection is a watchface
- Onthebutton is a watchface
- Rumbletime is a watchface
- Fuzzy Time is a watchface
- Changed example UUID's to avoid appstore collisions
### Changes for Documentation:
- Add note about datalogging size

View File

@@ -1,113 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Pebble SDK 2.0 DP2 - Changelog
date: 2013-09-24
---
>2.0 DP2.1
> We do not like making releases twice a week but we really wanted to fix the iOS/PebbleKit JS bug and so here it is. PebbleKit JS can now receive message on iOS and on Android. You only need to update your SDK for this to work. We will not release new versions of the mobile apps.
>The rest of the DP2 release notice below still applies.
### Known problems and bugs
- Data Logging does not work on iOS7
- The watch can run out of memory if the applications do not release the memory properly
- On iOS, PebbleKit JS can not receive app messages (fixed in the DP2.1 release)
### In a nutshell
* The format of applications has changed. Every application now requires an `appinfo.json` file in its base directory. This file contains the UUID, name and resources of the application. For PebbleKit JS apps, it may also contain the keys used for app_message communication.
* The `pb-sdk` tool is gone. It is replaced by the `pebble` command line.
* Instead of having the phone connect to the developer box, the developer tools will connect to the mobile application. When you turn on developer mode on your phone, it will display the IP address that you should use to connect to the phone. You can set a `PEBBLE_PHONE` environment variable to avoid retyping this all the time.
* Fixed most blocking bugs reported on Developer Preview 1 (details below)
* The Developer Guide has been completely rewritten and also includes a migration guide.
### Pebble Firmware
- Fixed a bug where launching an application through the bluetooth protocol would cause the app to be re-launched if it was already running.
- Added support for the middle button in the Golf app. This will send a message that is received by PebbleKit on iOS and Android.
- Tap event is now disabled during a vibration (to avoid triggering the event)
- Bumped firmware version and added tests to make sure that old apps will not run on the new firmware and vice-versa
- Fixed various issue with firmware updates
- AppLog does not need to be enabled manually anymore. It is automatically enabled by the `pebble` tool.
### Pebble SDK
- Finalized conversion to new dynamic memory model: all _init functions have been replaced by _create() equivalent that return a pointer to a newly allocated and initialized structure (gbitmap_init functions, gpath_init, property_animation_init and app_sync_init have been updated to the new style)
- Trigger a battery event when the percentage of battery charge changes (will trigger every 2%)
- Data Spooling now takes a `void*` pointer (to avoid useless casting in developer code)
- Data spooling session ids are now random
- persist_read_int now returns 0 if the key does not exist (as per documentation)
- Global static variables were not initialized properly
- Fix a dataspooling bug where sometimes the close message did not contain the correct session id
- Added a bluetooth_connection_service_peek() function
- Export atol/atoi functions
- Export app_comm_get_sniff_interval
- As a developer, I can call the atan()/atan2() function to compute an arc-tangent
- Renamed DataSpooling into DataLogging
- Defined a new Design Pattern to subclass layers and included an example based on the famous Progress Bar layer (`watchapps/feature_layer_data`)
### PebbleKit iOS/Android
- Redesigned completely the Android API for Data Logging (ex data spooling)
### PebbleKit JavaScript
- Fixed a bug where only single digit integers would be passed as integers
- On Android, the apps are now available in the "Webapps" menu
- On iOS and Android, applications will keep on running once they are started (but they do not start automatically yet)
- On iOS, you need to tap the appname to run it.
- On iOS, to allow for `openURL` to work, you need to open the javascript console first
- On iOS and Android, javascript `console.log` are sent over the developer connection (available with `pebble logs`)
- You can now send array of bytes by passing an array of integers to `sendAppMessage()`
- The keys in the appinfo.json file is now optional and you can use integers in strings as keys
- If a received message as a key that is not listed in the `appKeys` block, the integer will be converted to a string
- A bug where the navigation stack could be corrupted when calling `openURL` is fixed
### pb-sdk
- Renamed pb-sdk into pebble
- Added a --version option
- Added a command to clean current project
- Added an example of using APPLOG in the default generated project
- Return meaningful error codes to the shell
- Fixed a bug where `pb-sdk list` would fail if no apps are installed
- Added a --javascript option to `pb-sdk new-project` to create a template of JS code and automatically generate the appinfo.json
- Automatically detect old projects, refuse to build and offer the option to update the project
- Added `convert-project` command to update old projects to the new style (note: this will not update the source code)
- Added clean error message if a resource is missing
### iOS Application
- The developer preview iOS application will automatically offer new version of the beta firmware
- Added support for middle button in golf app
- Some iOS7 fixes
- Switched to TestFlight for distribution and crash reports
### Android Application
- The developer preview Android application will automatically offer new version of the beta firmware
- Added support for middle button in golf app
- Switched to TestFlight for distribution and crash reports
### Pebble SDK Examples
- Added an example for the persistent storage APIs
- Fixed all the iOS examples to build out of the box
- Reworked the Ocean Data Survey example

View File

@@ -1,122 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Pebble SDK 2.0 DP3 - Changelog
date: 2013-10-21
---
This version brings some major improvements and a lot of bugfixes. In a nutshell, the big changes are:
* PebbleKit JavaScript now supports geolocation on all platforms
* Pebble supports the ANCS protocol. See details below.
This is a private release under NDA.
### Pebble and ANCS
Pebble has been working on integrating Bluetooth Low Energy (BLE) technology into our upcoming software releases. The initial goal for this work is to greatly enhance the notification experience between a Pebble and a BLE-capable iOS7 device (the iPhone4S and later) - this leverages the "ANCS" notification feature of iOS7. A requirement for the public release of BLE-capable Pebble SW is that it will not change the Android experience. We will work on enhancing the BLE experience specifically for Android users in future SW releases.
If you wish to help Pebble test BLE and ANCS, please read this carefully, this is pre-release software and there are still areas of the experience we are actively enhancing. We greatly appreciate your help in testing these important features :-)
Pebble SDK DP3 (and up) include BLEs capabilities. Download the firmware and mobile apps as instructed in the installation instructions. You do not need anything else.
To configure ANCS and BLE:
- If you already had email configured in the iOS Pebble app, go into the Pebble app and turn that OFF. With ANCS, email notifications will automatically mirror the notifications that show up on your phone.
- The first time you set this up (after you install BLE/ANCS firmware) you will need to pair your phone with the watch to make the BTLE connection.
- On the watch, go into the "Settings" view, and select "Bluetooth".
- On your iOS7 iPhone go into the "Settings" app, select "Bluetooth".
- You should see an entry called "Pebble-LExxxx" where xxxx is the 4 digit code that is shown at the top of the Pebble's Bluetooth screen. Select that entry, and confirm pairing.
- Ensure that BOTH traditional Bluetooth and BLE are paired. You will not be able to perform all of the functions (such as handling phone calls) if the Bluetooth-Classic connection is not working.
- We are actively working on enhancements to pairing, so this process will change as we near public release.
Known issues:
- Only pairing from iOS BT Settings works for now. In-Pebble-app pairing is still TODO.
- If you have a red bar "Notifications require additional setup" in your iOS app, this will not disappear when LE is paired / ANCS is activated. You can safely ignore it.
- Gmail/IMAP in Pebble app + ANCS = Duplicate emails. We recommend turning off email accounts from the Pebble iOS app.
- "Forget" from the watch's BT settings menu doesn't work as expected. iDevice immediately reconnects again.
- All notifications have same icon
- Max message length is shorter than Bluetooth Classic.
- Impact on battery life: we are actively characterizing and working on this, but it is currently less than Bluetooth-Classic only.
Please report any bugs by email to: [ancsbug@getpebble.com](mailto:ancsbug@getpebble.com)!
**Remember, this release is under NDA. Please do not share word of this new feature. Thanks a lot!**
### Known problems and bugs
* Data Logging still does not work on iOS7
* On iOS, to try the "openURL()" function, you must first click the "Details Indicator" button on the table view that lists the JavaScript process
* On Android, to upgrade an existing JavaScript app, you must first kill it in the "JS App Processes" view (look for the Skull And Bones button)
* On some Android phones running 4.1, we have encountered a situation where location services were not working. This problem and the appropriate fix is described by Google [in this forum post](http://productforums.google.com/forum/#!msg/mobile/LEPcl9e3dYE/3LZEhiWACigJ).
### Pebble Firmware
- Fix a bug where Pebble would keep vibrating after answering a call
### Pebble SDK
- Fix a bug which caused all apps to share the same persistent storage file
### PebbleKit iOS/Android
- Removed some deprecated/private APIs call from PebbleKit-iOS
- Update PebbleKit-iOS project files to Xcode 5
- Fix PebbleKit Android build - moved libraries to libs/
### PebbleKit JavaScript
- Getting current location now works on iOS and Android. It is also possible to watch the current position and be notified when it changes.
- Fixed a bug on iOS where sending multiple digits number would not work
- Fixed a bug with the 2.1 release on Android where it would be impossible to use AppMessage (with PebbleKit JS)
- Receiving byte arrays now also works on iOS
- Added Pebble.getAccountToken() to get a unique token for the current user account (Note: this is not documented yet.)
### pebble tool
- Do not return 0 if something bad happened
- Display the footprint of the app in RAM and the available heap space
### Pebble iOS Application
- Fixed a UI bug on iOS7 when deleting an app
- Fixed the Developer Mode UI on iOS7
#### 2013 10 25 - 2.0-DP3.1
We have release a 3.1 update for the iOS application which should fix the most common crash for the app.
### Pebble Android application
- Fixed a bug where the Android app would continuously try to connect to the Pebble even after disconnecting/unpairing
- Fixed a bug where Facebook notifications would have duplicated content in the name field and the main field
- Automatically start an app after installation
- Fixed a bug where it would be impossible to skip the onboarding process
- Fixed a bug where switching the device orientation during firmware upgrade would cause the upgrade to start again
### Pebble SDK Examples
- Fixed a crash in dropzone
- Improved the weatherjs example to use geolocation and display the name of the city
- Added a very cool arcade game to demonstrate use of persistent storage (watchapps/pebble_arcade)
### Documentation
- Simplified installation instructions for Linux
- Fixed a lot of broken links
- Added a chapter on iOS whitelisting
- Added a chapter on fonts
- Reworked most of the developer guides

View File

@@ -1,79 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Pebble SDK 2.0.0 - Changelog
date: 2014-02-03
---
This is the first public release of Pebble SDK 2.0 and Pebble firmware 2.0.
## What has changed since BETA7
Overview:
* We have fixed various crashes in the firmware (this was pre-released as 2.0-RC, 2.0-RC2 and 2.0-RC3)
* We have restored support for direct Bluetooth connection from the computer to the pebble in the `pebble` tool
* PebbleKit iOS now includes armv7s, arm64 and x86_64 libraries - There is a known bug in PebbleKit iOS 2.0.0 that can cause your application to crash when it is in the background. Please do not use this version to submit an application to Apple.
## Known bugs and issues
* DataLogging disabled
Pebble iOS 2.0.0 app can enter a crashloop situation when corrupted datalogging bytes are received from Pebble. To avoid this problem, we have disabled the datalogging APIs in firmware 2.0.0. We will re-enable datalogging when the iOS app 2.0.1 is available on the App Store.
* PebbleKit iOS 2.0.0
Can cause 3rd party applications to crash when it is in the background. Please do not use this version to submit an application to Apple. This will be fixed in 2.0.1.
### Changes for Firmware:
Changes since 2.0-RC3:
* fix a deadlock when sending datalogging information
* remove the "Your Pebble has reset" message
The changes between 2.0-BETA7 and 2.0-RC3 were:
* fixes a number of crashes
* app no longer gets killed when it cancels an invalid timer
* removes “persist_raw -9” message
* low battery message always uses the right icon
* fixes crash on watch shutdown
* fixes crash when using accel
### Changes for PebbleKit iOS:
* Updated our version of CocoaLumberJack to fix a crash that could happen when logging in the background
* Updated the build script to actually produce armv7s, arm64 and x86_64 dynamic libraries
* Improve the datalogging protocol (between PebbleApp and PebbleKit) to be more efficient
### Changes for PebbleKit Android:
No changes.
### Changes for SDK Tools:
* We have restored support for direct Bluetooth connection from the computer to the pebble in the `pebble` tool
* Better handling of timeout errors with the websockets
### Changes for Examples:
No changes.
### Changes for Documentation:
* Add parameter `did_vibrate` to AccelData and explanation.
* Add parameter `timestamp` to AccelData and explanation.

View File

@@ -1,60 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Pebble SDK 2.0.1 - Changelog
date: 2014-02-20
---
This is a minor update to the Pebble SDK and the Pebble firmware.
## What has changed since 2.0.0
Overview:
- We have re-enabled data logging in the Pebble firmware
## Known bugs and issues
* PebbleKit iOS 2.0.0
Can cause 3rd party applications to crash when it is in the background. Please do not use this version to submit an application to Apple. This will be fixed in a later release.
## Detailed list of changes
### Changes for Firmware:
* We have re-enabled the data logging APIs.
### Changes for PebbleKit iOS:
* No changes.
### Changes for PebbleKit Android:
* No changes.
### Changes for SDK Tools:
* No changes.
### Changes for Examples:
* Reduce the accel discs step time
### Changes for Documentation:
* Updated documentation on Android intents
* Updated documentation on AppMessage, AppSync, Dictionary, Typlets

View File

@@ -1,63 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Pebble SDK 2.0.2 - Changelog
date: 2014-03-18
---
This is another minor update to the Pebble SDK and the Pebble firmware.
## What has changed since 2.0.1
Overview:
- Fixes issue that prevented some users from being able to upgrade to 2.0.
- Support for XCode 5.1
- Removed Pillow as dependency for the SDK
## Known bugs and issues
None.
## Detailed list of changes
### Changes for Firmware:
* Fix a bug that could prevent installation fo the firmware
### Changes for PebbleKit iOS:
* No changes.
### Changes for PebbleKit Android:
* No changes.
### Changes for SDK Tools:
* LibPebble upgrade to remove PIL dependency
* replaced PIL with pypng for taking screenshots
### Changes for Examples:
* Update the todolist example to use graphics_text_layout_get_content_size instead of graphics_text_layout_get_max_used_size
* Port improvements to simplicity from firmware to examples
* Update quotes app for ready event
### Changes for Documentation:
* Fixed error in API docs for accel
* Fix javascript close URL in the javascript doc

View File

@@ -1,70 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Pebble SDK 2.1.1 - Changelog
date: 2014-05-08
---
## What has changed since 2.1
This release fixes a bug which caused the `pebble` tool to throw an exception when a Pebble app crashed. This is the only fix and we are not releasing a firmware 2.1.1, only the SDK is updated.
## What has changed since SDK 2.0.2
Overview:
* Pebble dynamic memory allocation has been improved and will now detect when you try to free() memory twice.
* With Pebble 2.1 your application will be killed and a message is shown in the console so you can detect and fix this problem, instead of potentially causing a memory corruption issue.
* IMPORTANT: You will need to update your Pebble to run apps built with the 2.1 SDK. Applications compiled with the SDK 2.1 will not appear in the menu and will not run on Pebble firmware 2.0.
## Detailed List of Changes:
### Changes for Firmware:
* Fixed crash caused by calling number_window_set_label
* Fixed white line at the bottom of MenuLayer when last row is selected
* Fixed an issue where the watch would get into a reset loop after boot
* Fixed issue that sometimes caused persistent storage values to not persist
* Fixed issue where caller ID shows info from the previous call
* Fixed caller ID sometimes not displaying on outgoing calls
* Pebble dynamic memory allocation has been improved. Your application will now be killed when you try to free() memory twice
* Apps can no longer crash the watch on app exit
* Bluetooth reconnection is more reliable
* Battery monitor is more consistent
* Multiple power reduction improvements
* Documentation improvements
* Clip text instead of truncating when vertical space is inadequate
* Notifications can be cleared via the Notification section in the Settings menu
### Changes for PebbleKit iOS:
* Some improvements to datalogging to help troubleshoot issues
### Changes for PebbleKit Android:
* No changes
### Changes for SDK Tools:
* Allow firmware bundles to be installed with the install command
* Allow SDK location to be overridden by the `PEBBLE_SDK_PATH` environment variable
* Replaced PIL with pypng for taking screenshots
* Fixed extra row always being added to screenshots
### Changes for Examples:
* Removed ToDoList demo from SDK examples
### Changes for Documentation:
* Various documentation fixes and improvements

View File

@@ -1,66 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Pebble SDK 2.1 - Changelog
date: 2014-05-06
---
## What has changed since SDK 2.0.2
Overview:
* Pebble dynamic memory allocation has been improved and will now detect when you try to free() memory twice.
* With Pebble 2.1 your application will be killed and a message is shown in the console so you can detect and fix this problem, instead of potentially causing a memory corruption issue.
* IMPORTANT: You will need to update your Pebble to run apps built with the 2.1 SDK. Applications compiled with the SDK 2.1 will not appear in the menu and will not run on Pebble firmware 2.0.
## Detailed List of Changes:
### Changes for Firmware:
* Fixed crash caused by calling number_window_set_label
* Fixed white line at the bottom of MenuLayer when last row is selected
* Fixed an issue where the watch would get into a reset loop after boot
* Fixed issue that sometimes caused persistent storage values to not persist
* Fixed issue where caller ID shows info from the previous call
* Fixed caller ID sometimes not displaying on outgoing calls
* Pebble dynamic memory allocation has been improved. Your application will now be killed when you try to free() memory twice
* Apps can no longer crash the watch on app exit
* Bluetooth reconnection is more reliable
* Battery monitor is more consistent
* Multiple power reduction improvements
* Documentation improvements
* Clip text instead of truncating when vertical space is inadequate
* Notifications can be cleared via the Notification section in the Settings menu
### Changes for PebbleKit iOS:
* Some improvements to datalogging to help troubleshoot issues
### Changes for PebbleKit Android:
* No changes
### Changes for SDK Tools:
* Allow firmware bundles to be installed with the install command
* Allow SDK location to be overridden by the `PEBBLE_SDK_PATH` environment variable
* Replaced PIL with pypng for taking screenshots
* Fixed extra row always being added to screenshots
### Changes for Examples:
* Removed ToDoList demo from SDK examples
### Changes for Documentation:
* Various documentation fixes and improvements

View File

@@ -1,50 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Pebble SDK 2.2 - Changelog
date: 2014-06-04
---
## Detailed List of Changes:
### Changes for Firmware:
* Music app redesign to fix some layout issues & add progress bar
* Fix persist reads returning too little data if previously partially read
* Additional stability improvements
* Alarm now vibrates for 10 min instead of 1 min
* Launcher menu is now re-orderable. Hold the select button to enter reorder mode
* Volume control in the music app. Hold the select button in the music app to enter volume control mode
### Changes for PebbleKit iOS:
* Removed PBWatch+PhoneVersion (moved to PebblePrivateKit)
* Make PBWatch+Version report the correct version
* Fixed a crash when calling PBNumber description
### Changes for PebbleKit Android:
No changes
### Changes for SDK Tools:
No changes
### Changes for Examples:
No changes
### Changes for Documentation:
No changes

View File

@@ -1,68 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Pebble SDK 2.3 - Changelog
date: 2014-06-30
---
## Detailed List of Changes:
### Changes for Firmware:
* Don't generate multiple single click events on release if a repeating click handler is also used
* Fixed a small memory leak when destroying number_layer objects
* Fixed a menu_layer display bug when header height is set to 0
* Allow app developers to supply their own ldscript
* Give a better error message when an unsupported libc function is used
* *_destroy functions now correctly do nothing when called with NULL pointers
* Fixed some BT LE connectivity issues
* Fixed a crash when we ran out of persist space
* Fixed a crash on reconnect when a user had a lot of pending iOS notifications
* Fixed an issue where the watch would continue to vibrate after a call is ended
* Fixed a display issue in Bluetooth settings when the status bar incorrectly says "Now Discoverable" in airplane mode
* Fixed a display issue with the notification font settings
* Fixed a display issue with the music app showing stale information when bluetooth is disconnected.
* Added the ability to skip to the next and previous notification by double clicking the up and down buttons
* Disabled the use of the back button for the Bluetooth pairing screen and the Alarm screen
* Show a status bar icon when notifications are set to "Phone Calls Only"
### Changes for PebbleKit iOS:
* Removed Bluetooth LE code from PebbleKit
* Improvements to data logging to help troubleshoot issues
* Removed PBWatch+PhoneVersion and +Polling
* Made PBWatch+Version report the correct version
* Fixed a crash when calling PBNumber description
* Changed imports from \<PebbleKit/HeaderName.h\> to "HeaderName.h" format
* Fixed on rare race-condition when sending data between phone and watch
* Made PebbleKit.podspec pass most-recent CocoaPod linter
* Prefixed internally used logging classes to fix conflict when using CocoaLumberjack in your app
* Made existing logging more descriptive
### Changes for PebbleKit Android:
No changes
### Changes for SDK Tools:
No changes
### Changes for Examples:
No changes
### Changes for Documentation:
* Added documentation for the calloc libc function
* Documented that text drawing functions use UTF-8 and will return errors on invalid input

View File

@@ -1,44 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Pebble SDK 2.4.1 - Changelog
date: 2014-08-12
---
## Detailed List of Changes:
### Changes for Firmware:
* Fix a compilation problem that caused firmware 2.4 to reduce the amount of memory available to apps
### Changes for PebbleKit iOS:
No changes
### Changes for PebbleKit Android:
No changes
### Changes for SDK Tools:
No changes
### Changes for Examples:
No changes
### Changes for Documentation:
No changes

View File

@@ -1,53 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Pebble SDK 2.4 - Changelog
date: 2014-08-11
---
## Detailed List of Changes:
### Changes for Firmware:
* Fix a potential crash when using scroll layers or animations
* Added support for realloc
* Added a gbitmap_create\_blank function to create empty bitmaps of a fixed size
* Added number_window\_get_window()
* Fixed a crash with atan2_lookup when high input values were used
* Fixed a bug where TupletInteger could not be used with unsigned integers
* Fixed several bluetooth reliability issues
* Fixed a case where the "Setup notifications" banner would erroneously show in the iOS Pebble app
* Fixed a bug with the music app where media playing faster than real time could not be paused
* Fixed a bug where the notifications view could show a rapidly increasing counter for number of notifications when first displayed
* Fixed a bug where switching watchfaces could cause the same watchface to be relaunched
### Changes for PebbleKit iOS:
No changes
### Changes for PebbleKit Android:
No changes
### Changes for SDK Tools:
No changes
### Changes for Examples:
No changes
### Changes for Documentation:
* Improved documentation around click handling

View File

@@ -1,84 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Pebble SDK 2.5 - Changelog
date: 2014-09-18
---
>If you are upgrading from a previous version of the SDK, you will need to run the `pebble clean` command before using the SDK 2.5 with your project.
##Major Changes
* FW 2.5 includes an optimized version of ``snprintf`` (and related functions like ``APP_LOG``, etc) that does not support some length format specifiers previously supported (%hh, %ll, %j, %z, %t). The list of supported specifiers has been updated in the ``snprintf`` documentation. For those of you that use these previously-supported specifiers, please do not hesitate to [contact us](/contact) and we'd be happy to assist you with updating your code.
* Added [compass](/guides/events-and-services/compass) support.
* Enforced versionLabel formatting in appinfo.json in preparation for app auto updates.
* Added support for Pebble app relaunch on iOS when a Pebble watch is in proximity.
* Added notification dismissal support on iOS8.
* Added emoji support to Pebble notifications and system fonts.
## Detailed List of Changes:
### Changes for Firmware:
* Added functions ``heap_bytes_free`` and ``heap_bytes_used`` to view current heap memory usage.
* Added support for ``uuid_equal`` and ``uuid_to_string``.
* Added function ``accel_raw_data_service_subscribe`` to get accelerometer data with a single timestamp for all samples (significantly reduces memory usage for apps that do not depend on timestamps).
* Added [compass](/guides/events-and-services/compass) support.
* Added emoji support to Pebble notifications and system fonts `GOTHIC_24_BOLD`, `GOTHIC_18` and `GOTHIC_18_BOLD`.
* Fixed a bug that would cause a crash if a screen shot was taken while one was already in progress.
* Fixed an issue where Pebble APIs would use non-reentrant versions of standard C functions causing unexpected changes to return values.
* Fixed a bug with accel_service that could result in memory being freed twice.
* Fixed a bug where Golf API would show stale information on disconnect.
* Fixed a bug that prevented calling ``menu_layer_set_selected_index`` before ``menu_layer_set_callbacks``.
* Fixed a bug which would sometimes cause the command line logging tool to crash when a watchapp crashed.
* Fixed a bug that would cause the sample rate of the accelerometer to be reset when subscribing.
* Added support for Pebble app relaunch on iOS when a Pebble watch is in proximity.
* Added support for notification dismissal on iOS8.
* Fixed numerous bluetooth reliability & connection issues.
* Fixed a reset and other various bugs related to Data Logging.
* Fixed a bug that allowed backing out of FW update screen.
* Fixed a bug that would cause animations between windows to be slow.
* Fixed a bug where the Date UI would allow selection of invalid dates.
* Fixed a bug which would prevent the down button from scrolling through notification history.
* Fixed a bug with AVRCP that could lead to a crash.
* Set backlight to stay on during alarm ringing.
* Changed the default backlight setting to AUTO.
* Fixed a bug which would allow developers to ask for more than 25 accel samples per update.
* Added check for NULL parameter in ``gpath_draw_filled``.
### Changes for PebbleKit iOS:
PebbleKit iOS has been removed from the SDK download. Please find the latest PebbleKit iOS on [GitHub](https://github.com/pebble/pebble-ios-sdk) or on [CocoaPods](http://cocoapods.org/) under 'PebbleKit'.
### Changes for PebbleKit Android:
PebbleKit Android has been removed from the SDK download. Please find the latest PebbleKit Android on [GitHub](https://github.com/pebble/pebble-android-sdk).
### Changes for SDK Tools:
* Enforced versionLabel formatting in appinfo.json in preparation for app auto updates.
### Changes for Examples:
* Added [compass example]({{site.links.examples_org}}/feature-compass) application.
### Changes for Documentation:
* Added ``CompassService`` API document.
* Added missing ``calloc`` and ``realloc`` documentation.
* Improved ``tick_timer_service_subscribe`` documentation.
* Added missing ``RotBitmapLayer`` documentation.
* Corrected ``window_single_click_subscribe`` API entry.
* Corrected time_t time() function to specify that epoch adjusts for timezone and DST.
* Fixed typo in the ``AppMessage`` documentation.
* Improved ``gbitmap_create_with_data`` documentation.
* Fixed typo in documentation for ``resource_get_handle``.

View File

@@ -1,35 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Pebble SDK 2.6.1 - Changelog
date: 2014-10-01
---
> This release is a hotfix for the SDK 2.6 release
### Changes for SDK Tools:
* Fix bug preventing use of `pebble analyze-size`
* Fix bug that caused compile errors with the use of custom fonts
---
### Pebble SDK 2.6 Release Summary ([full changelog](/sdk/changelogs/2.6/))
##### Major Changes:
* Add support for [background apps](/guides/events-and-services/background-worker) with ``AppWorker``
* Add ``graphics_capture_frame_buffer``, ``graphics_release_frame_buffer``, ``graphics_frame_buffer_is_captured`` APIs to expose framebuffer
* Add ``WatchInfo`` APIs to expose watch color, watch model, and firmware version
* Add quick launch support
* Bring back select-button-to-dismiss-notification on Android & iOS < 8
* Add --worker option to `pebble new-project` to create file structure for apps with background workers
* Add background worker [example]({{site.links.examples_org}}/feature-background-counter)

View File

@@ -1,47 +0,0 @@
---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Pebble SDK 2.6 - Changelog
date: 2014-09-30
---
> The symbols for `NUM_ANIMATION_CURVE` and `AnimationTimingFunction` have been removed in SDK 2.6. They were exposed in pebble.h in a previous release, but were not documented and are not used for ``Animation`` or ``PropertyAnimation`` APIs.
## Detailed List of Changes:
### Changes for Firmware:
* Add support for [background apps](/guides/events-and-services/background-worker/) with ``AppWorker``
> NOTE: The Background Worker API is not intended to be used as a wakeup mechanism for timer-based events or activities. SDK 2.7 will include a new Wakeup API that will allow you to set a timer that automatically launches your app in the foreground. Please do not use the Background Worker API to set such wakeups.
* Improve bluetooth connection service by only reporting disconnections of a certain length in time
* Add ``graphics_capture_frame_buffer``, ``graphics_release_frame_buffer``, ``graphics_frame_buffer_is_captured`` APIs to expose framebuffer
* Add ``WatchInfo`` APIs to expose watch color, watch model, and firmware version
* Fix bug where reading an existing key from persistent storage would fail
* Fixed Sports API bug causing menu item to not always appear in app launcher
* Fix bug with PebbleKit iOS and AppMessage timeouts
* Add quick launch support
* Bring back select-button-to-dismiss-notification on Android & iOS < 8
* Re-enable vibration when done charging
* Improve battery life
### Changes for SDK Tools:
* Add a --generate command line option to the coredump command
* Add --worker option to `pebble new-project` to create file structure for apps with background workers
### Changes for Examples:
* Add background worker [example]({{site.links.examples_org}}/feature-background-counter)
### Changes for Documentation:
* Add [AppWorker Guide](/guides/events-and-services/background-worker/)
* Add documentation for ``Worker``, ``AppWorker``, ``WatchInfo``

Some files were not shown because too many files have changed in this diff Show More