mirror of
https://github.com/google/pebble.git
synced 2025-04-18 18:54:44 -04:00
Import the pebble dev site into devsite/
This commit is contained in:
parent
3b92768480
commit
527858cf4c
1359 changed files with 265431 additions and 0 deletions
12
devsite/.env.sample
Normal file
12
devsite/.env.sample
Normal file
|
@ -0,0 +1,12 @@
|
|||
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
Normal file
12
devsite/.gitignore
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
__public__
|
||||
.sass-cache/
|
||||
.env
|
||||
tmp/
|
||||
source/stylesheets/
|
||||
log/
|
||||
.bundle/
|
||||
coverage/
|
||||
node_modules/
|
||||
vendor/
|
||||
.ruby-version
|
||||
.jekyll-metadata
|
0
devsite/.rspec
Normal file
0
devsite/.rspec
Normal file
155
devsite/.scss-lint.yml
Normal file
155
devsite/.scss-lint.yml
Normal file
|
@ -0,0 +1,155 @@
|
|||
# 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
|
44
devsite/Gemfile
Normal file
44
devsite/Gemfile
Normal file
|
@ -0,0 +1,44 @@
|
|||
# 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
|
138
devsite/Gemfile.lock
Normal file
138
devsite/Gemfile.lock
Normal file
|
@ -0,0 +1,138 @@
|
|||
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
|
184
devsite/README.md
Normal file
184
devsite/README.md
Normal file
|
@ -0,0 +1,184 @@
|
|||
# [developer.pebble.com][site]
|
||||
|
||||
[][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
|
28
devsite/Rakefile
Normal file
28
devsite/Rakefile
Normal file
|
@ -0,0 +1,28 @@
|
|||
# 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
|
111
devsite/_config.yml
Normal file
111
devsite/_config.yml
Normal file
|
@ -0,0 +1,111 @@
|
|||
# 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
|
28
devsite/app.json
Normal file
28
devsite/app.json
Normal file
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"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
|
||||
}
|
||||
}
|
||||
}
|
53
devsite/config.ru
Normal file
53
devsite/config.ru
Normal file
|
@ -0,0 +1,53 @@
|
|||
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]]
|
||||
}
|
4971
devsite/docs.json
Normal file
4971
devsite/docs.json
Normal file
File diff suppressed because one or more lines are too long
12
devsite/docs/development.md
Normal file
12
devsite/docs/development.md
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Pebble Developer Site · 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.
|
84
devsite/docs/environment.md
Normal file
84
devsite/docs/environment.md
Normal file
|
@ -0,0 +1,84 @@
|
|||
# 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=
|
||||
```
|
305
devsite/docs/markdown.md
Normal file
305
devsite/docs/markdown.md
Normal file
|
@ -0,0 +1,305 @@
|
|||
# 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:
|
||||
|
||||
```
|
||||

|
||||

|
||||
```
|
||||
|
||||
### 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.
|
||||
|
||||
```
|
||||

|
||||
```
|
||||
|
||||
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)
|
||||
```
|
16
devsite/docs/troubleshooting.md
Normal file
16
devsite/docs/troubleshooting.md
Normal file
|
@ -0,0 +1,16 @@
|
|||
# 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`
|
428
devsite/js-docs/pkjs/Pebble.js
Normal file
428
devsite/js-docs/pkjs/Pebble.js
Normal file
|
@ -0,0 +1,428 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
377
devsite/js-docs/rocky/CanvasRenderingContext2D.js
Normal file
377
devsite/js-docs/rocky/CanvasRenderingContext2D.js
Normal file
|
@ -0,0 +1,377 @@
|
|||
/**
|
||||
* 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> 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> var ctx = drawEvent.context;<br> 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) { };
|
64
devsite/js-docs/rocky/Console.js
Normal file
64
devsite/js-docs/rocky/Console.js
Normal file
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* 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) { };
|
121
devsite/js-docs/rocky/Date.js
Normal file
121
devsite/js-docs/rocky/Date.js
Normal file
|
@ -0,0 +1,121 @@
|
|||
/**
|
||||
* 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() { };
|
||||
|
||||
|
58
devsite/js-docs/rocky/global.js
Normal file
58
devsite/js-docs/rocky/global.js
Normal file
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* 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) { };
|
262
devsite/js-docs/rocky/rocky.js
Normal file
262
devsite/js-docs/rocky/rocky.js
Normal file
|
@ -0,0 +1,262 @@
|
|||
/**
|
||||
* 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>> 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>> 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> rocky.requestDraw();<br>});`
|
||||
*/
|
||||
rocky.requestDraw = function() { };
|
153
devsite/lib/c_docs/doc_class.rb
Normal file
153
devsite/lib/c_docs/doc_class.rb
Normal file
|
@ -0,0 +1,153 @@
|
|||
# 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
|
98
devsite/lib/c_docs/doc_element.rb
Normal file
98
devsite/lib/c_docs/doc_element.rb
Normal file
|
@ -0,0 +1,98 @@
|
|||
# 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
|
58
devsite/lib/c_docs/doc_enum_value.rb
Normal file
58
devsite/lib/c_docs/doc_enum_value.rb
Normal file
|
@ -0,0 +1,58 @@
|
|||
# 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
|
178
devsite/lib/c_docs/doc_group.rb
Normal file
178
devsite/lib/c_docs/doc_group.rb
Normal file
|
@ -0,0 +1,178 @@
|
|||
# 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
|
165
devsite/lib/c_docs/doc_member.rb
Normal file
165
devsite/lib/c_docs/doc_member.rb
Normal file
|
@ -0,0 +1,165 @@
|
|||
# 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
|
154
devsite/lib/c_docs/doxygen_processor.rb
Normal file
154
devsite/lib/c_docs/doxygen_processor.rb
Normal file
|
@ -0,0 +1,154 @@
|
|||
# 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
|
49
devsite/lib/pebble_documentation.rb
Normal file
49
devsite/lib/pebble_documentation.rb
Normal file
|
@ -0,0 +1,49 @@
|
|||
# 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
|
189
devsite/lib/pebble_documentation_c.rb
Normal file
189
devsite/lib/pebble_documentation_c.rb
Normal file
|
@ -0,0 +1,189 @@
|
|||
# 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
|
120
devsite/lib/pebble_documentation_js.rb
Normal file
120
devsite/lib/pebble_documentation_js.rb
Normal file
|
@ -0,0 +1,120 @@
|
|||
# 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
|
203
devsite/lib/pebble_documentation_pebblekit_android.rb
Normal file
203
devsite/lib/pebble_documentation_pebblekit_android.rb
Normal file
|
@ -0,0 +1,203 @@
|
|||
# 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
|
240
devsite/lib/pebble_documentation_pebblekit_ios.rb
Normal file
240
devsite/lib/pebble_documentation_pebblekit_ios.rb
Normal file
|
@ -0,0 +1,240 @@
|
|||
# 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
|
140
devsite/lib/search_markdown.rb
Normal file
140
devsite/lib/search_markdown.rb
Normal file
|
@ -0,0 +1,140 @@
|
|||
# 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
|
81
devsite/lib/toc_generator.rb
Normal file
81
devsite/lib/toc_generator.rb
Normal file
|
@ -0,0 +1,81 @@
|
|||
# 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
|
53
devsite/plugins/blog_authors_generator.rb
Normal file
53
devsite/plugins/blog_authors_generator.rb
Normal file
|
@ -0,0 +1,53 @@
|
|||
# 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
|
69
devsite/plugins/blog_tags_generator.rb
Normal file
69
devsite/plugins/blog_tags_generator.rb
Normal file
|
@ -0,0 +1,69 @@
|
|||
# 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
|
50
devsite/plugins/environment_generator.rb
Normal file
50
devsite/plugins/environment_generator.rb
Normal file
|
@ -0,0 +1,50 @@
|
|||
# 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
|
23
devsite/plugins/filter_assetify.rb
Normal file
23
devsite/plugins/filter_assetify.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
# 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)
|
21
devsite/plugins/filter_basename.rb
Normal file
21
devsite/plugins/filter_basename.rb
Normal file
|
@ -0,0 +1,21 @@
|
|||
# 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)
|
28
devsite/plugins/filter_fake_platform.rb
Normal file
28
devsite/plugins/filter_fake_platform.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
# 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)
|
29
devsite/plugins/filter_hash_sort.rb
Normal file
29
devsite/plugins/filter_hash_sort.rb
Normal file
|
@ -0,0 +1,29 @@
|
|||
# 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)
|
28
devsite/plugins/filter_pluralize.rb
Normal file
28
devsite/plugins/filter_pluralize.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
# 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)
|
25
devsite/plugins/filter_slugize.rb
Normal file
25
devsite/plugins/filter_slugize.rb
Normal file
|
@ -0,0 +1,25 @@
|
|||
# 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)
|
236
devsite/plugins/generator_algolia.rb
Normal file
236
devsite/plugins/generator_algolia.rb
Normal file
|
@ -0,0 +1,236 @@
|
|||
# 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
|
166
devsite/plugins/generator_docs.rb
Normal file
166
devsite/plugins/generator_docs.rb
Normal file
|
@ -0,0 +1,166 @@
|
|||
# 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
|
65
devsite/plugins/generator_examples.rb
Normal file
65
devsite/plugins/generator_examples.rb
Normal file
|
@ -0,0 +1,65 @@
|
|||
# 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
|
94
devsite/plugins/generator_guides.rb
Normal file
94
devsite/plugins/generator_guides.rb
Normal file
|
@ -0,0 +1,94 @@
|
|||
# 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
|
35
devsite/plugins/generator_meetups.rb
Normal file
35
devsite/plugins/generator_meetups.rb
Normal file
|
@ -0,0 +1,35 @@
|
|||
# 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
|
58
devsite/plugins/generator_minify_js.rb
Normal file
58
devsite/plugins/generator_minify_js.rb
Normal file
|
@ -0,0 +1,58 @@
|
|||
# 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
|
62
devsite/plugins/generator_redirects.rb
Normal file
62
devsite/plugins/generator_redirects.rb
Normal file
|
@ -0,0 +1,62 @@
|
|||
# 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
|
54
devsite/plugins/jekyll_convertible.rb
Normal file
54
devsite/plugins/jekyll_convertible.rb
Normal file
|
@ -0,0 +1,54 @@
|
|||
# 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
|
85
devsite/plugins/jekyll_document.rb
Normal file
85
devsite/plugins/jekyll_document.rb
Normal file
|
@ -0,0 +1,85 @@
|
|||
# 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
|
45
devsite/plugins/jekyll_page.rb
Normal file
45
devsite/plugins/jekyll_page.rb
Normal file
|
@ -0,0 +1,45 @@
|
|||
# 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
|
45
devsite/plugins/jekyll_post.rb
Normal file
45
devsite/plugins/jekyll_post.rb
Normal file
|
@ -0,0 +1,45 @@
|
|||
# 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
|
323
devsite/plugins/pebble_markdown_parser.rb
Normal file
323
devsite/plugins/pebble_markdown_parser.rb
Normal file
|
@ -0,0 +1,323 @@
|
|||
# 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
|
||||
/^(.*)\ (>|>)\{?([a-z,0-9\-]*)\}?$/
|
||||
end
|
||||
|
||||
def regex_link_data
|
||||
/^(.*)\ (>|>)\{([a-z\-_,:0-9A-Z]+)\}$/
|
||||
end
|
||||
|
||||
def shortcode_to_platform(shortcode)
|
||||
platforms = {
|
||||
'CP' => 'cloudpebble',
|
||||
'LC' => 'local'
|
||||
}
|
||||
platforms[shortcode]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
42
devsite/plugins/tag_alert.rb
Normal file
42
devsite/plugins/tag_alert.rb
Normal file
|
@ -0,0 +1,42 @@
|
|||
# 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)
|
31
devsite/plugins/tag_asset_css.rb
Normal file
31
devsite/plugins/tag_asset_css.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
# 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)
|
31
devsite/plugins/tag_asset_js.rb
Normal file
31
devsite/plugins/tag_asset_js.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
# 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)
|
35
devsite/plugins/tag_author_link.rb
Normal file
35
devsite/plugins/tag_author_link.rb
Normal file
|
@ -0,0 +1,35 @@
|
|||
# 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)
|
36
devsite/plugins/tag_author_photo.rb
Normal file
36
devsite/plugins/tag_author_photo.rb
Normal file
|
@ -0,0 +1,36 @@
|
|||
# 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)
|
58
devsite/plugins/tag_cloudpebble_edit_gist.rb
Normal file
58
devsite/plugins/tag_cloudpebble_edit_gist.rb
Normal file
|
@ -0,0 +1,58 @@
|
|||
# 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)
|
43
devsite/plugins/tag_git_contributors.rb
Normal file
43
devsite/plugins/tag_git_contributors.rb
Normal file
|
@ -0,0 +1,43 @@
|
|||
# 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)
|
67
devsite/plugins/tag_guide_link.rb
Normal file
67
devsite/plugins/tag_guide_link.rb
Normal file
|
@ -0,0 +1,67 @@
|
|||
# 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)
|
35
devsite/plugins/tag_highlight.rb
Normal file
35
devsite/plugins/tag_highlight.rb
Normal file
|
@ -0,0 +1,35 @@
|
|||
# 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)
|
38
devsite/plugins/tag_if_starts_with.rb
Normal file
38
devsite/plugins/tag_if_starts_with.rb
Normal file
|
@ -0,0 +1,38 @@
|
|||
# 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)
|
30
devsite/plugins/tag_import_js.rb
Normal file
30
devsite/plugins/tag_import_js.rb
Normal file
|
@ -0,0 +1,30 @@
|
|||
# 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)
|
||||
|
35
devsite/plugins/tag_markdown.rb
Normal file
35
devsite/plugins/tag_markdown.rb
Normal file
|
@ -0,0 +1,35 @@
|
|||
# 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)
|
||||
|
39
devsite/plugins/tag_platform.rb
Normal file
39
devsite/plugins/tag_platform.rb
Normal file
|
@ -0,0 +1,39 @@
|
|||
# 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)
|
50
devsite/plugins/tag_screenshot_viewer.rb
Normal file
50
devsite/plugins/tag_screenshot_viewer.rb
Normal file
|
@ -0,0 +1,50 @@
|
|||
# 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)
|
18
devsite/scripts/generate-rocky-docs.sh
Executable file
18
devsite/scripts/generate-rocky-docs.sh
Executable file
|
@ -0,0 +1,18 @@
|
|||
#!/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
|
19
devsite/scripts/update-templates.sh
Executable file
19
devsite/scripts/update-templates.sh
Executable file
|
@ -0,0 +1,19 @@
|
|||
#!/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
|
33
devsite/scripts/video-encode.sh
Executable file
33
devsite/scripts/video-encode.sh
Executable file
|
@ -0,0 +1,33 @@
|
|||
# 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!"
|
51
devsite/source/404.html
Normal file
51
devsite/source/404.html
Normal file
|
@ -0,0 +1,51 @@
|
|||
---
|
||||
# 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>
|
42
devsite/source/_changelogs/2.0-BETA0.md
Normal file
42
devsite/source/_changelogs/2.0-BETA0.md
Normal file
|
@ -0,0 +1,42 @@
|
|||
---
|
||||
# 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.
|
74
devsite/source/_changelogs/2.0-BETA1.md
Normal file
74
devsite/source/_changelogs/2.0-BETA1.md
Normal file
|
@ -0,0 +1,74 @@
|
|||
---
|
||||
# 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
|
||||
|
97
devsite/source/_changelogs/2.0-BETA2.md
Normal file
97
devsite/source/_changelogs/2.0-BETA2.md
Normal file
|
@ -0,0 +1,97 @@
|
|||
---
|
||||
# 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
|
||||
|
117
devsite/source/_changelogs/2.0-BETA3.md
Normal file
117
devsite/source/_changelogs/2.0-BETA3.md
Normal file
|
@ -0,0 +1,117 @@
|
|||
---
|
||||
# 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
|
102
devsite/source/_changelogs/2.0-BETA4.md
Normal file
102
devsite/source/_changelogs/2.0-BETA4.md
Normal file
|
@ -0,0 +1,102 @@
|
|||
---
|
||||
# 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
|
||||
|
112
devsite/source/_changelogs/2.0-BETA5.md
Normal file
112
devsite/source/_changelogs/2.0-BETA5.md
Normal file
|
@ -0,0 +1,112 @@
|
|||
---
|
||||
# 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
|
92
devsite/source/_changelogs/2.0-BETA6.md
Normal file
92
devsite/source/_changelogs/2.0-BETA6.md
Normal file
|
@ -0,0 +1,92 @@
|
|||
---
|
||||
# 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
|
145
devsite/source/_changelogs/2.0-BETA7.md
Normal file
145
devsite/source/_changelogs/2.0-BETA7.md
Normal file
|
@ -0,0 +1,145 @@
|
|||
---
|
||||
# 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
|
113
devsite/source/_changelogs/2.0-DP2.md
Normal file
113
devsite/source/_changelogs/2.0-DP2.md
Normal file
|
@ -0,0 +1,113 @@
|
|||
---
|
||||
# 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
|
122
devsite/source/_changelogs/2.0-DP3.md
Normal file
122
devsite/source/_changelogs/2.0-DP3.md
Normal file
|
@ -0,0 +1,122 @@
|
|||
---
|
||||
# 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
|
79
devsite/source/_changelogs/2.0.0.md
Normal file
79
devsite/source/_changelogs/2.0.0.md
Normal file
|
@ -0,0 +1,79 @@
|
|||
---
|
||||
# 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.
|
||||
|
60
devsite/source/_changelogs/2.0.1.md
Normal file
60
devsite/source/_changelogs/2.0.1.md
Normal file
|
@ -0,0 +1,60 @@
|
|||
---
|
||||
# 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
|
||||
|
63
devsite/source/_changelogs/2.0.2.md
Normal file
63
devsite/source/_changelogs/2.0.2.md
Normal file
|
@ -0,0 +1,63 @@
|
|||
---
|
||||
# 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
|
||||
|
70
devsite/source/_changelogs/2.1.1.md
Normal file
70
devsite/source/_changelogs/2.1.1.md
Normal file
|
@ -0,0 +1,70 @@
|
|||
---
|
||||
# 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
|
66
devsite/source/_changelogs/2.1.md
Normal file
66
devsite/source/_changelogs/2.1.md
Normal file
|
@ -0,0 +1,66 @@
|
|||
---
|
||||
# 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
|
50
devsite/source/_changelogs/2.2.md
Normal file
50
devsite/source/_changelogs/2.2.md
Normal file
|
@ -0,0 +1,50 @@
|
|||
---
|
||||
# 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
|
68
devsite/source/_changelogs/2.3.md
Normal file
68
devsite/source/_changelogs/2.3.md
Normal file
|
@ -0,0 +1,68 @@
|
|||
---
|
||||
# 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
|
44
devsite/source/_changelogs/2.4.1.md
Normal file
44
devsite/source/_changelogs/2.4.1.md
Normal file
|
@ -0,0 +1,44 @@
|
|||
---
|
||||
# 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
|
||||
|
53
devsite/source/_changelogs/2.4.md
Normal file
53
devsite/source/_changelogs/2.4.md
Normal file
|
@ -0,0 +1,53 @@
|
|||
---
|
||||
# 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
|
84
devsite/source/_changelogs/2.5.md
Normal file
84
devsite/source/_changelogs/2.5.md
Normal file
|
@ -0,0 +1,84 @@
|
|||
---
|
||||
# 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``.
|
35
devsite/source/_changelogs/2.6.1.md
Normal file
35
devsite/source/_changelogs/2.6.1.md
Normal file
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
# 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)
|
47
devsite/source/_changelogs/2.6.md
Normal file
47
devsite/source/_changelogs/2.6.md
Normal file
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
# 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``
|
||||
|
39
devsite/source/_changelogs/2.7.md
Normal file
39
devsite/source/_changelogs/2.7.md
Normal file
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
# 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.7 - Changelog
|
||||
date: 2014-10-16
|
||||
---
|
||||
|
||||
## Detailed List of Changes:
|
||||
### Changes for Firmware:
|
||||
* Add ``Wakeup`` API
|
||||
* Add ``launch_reason`` API
|
||||
* Fix a bug that caused ``watch_info_get_color`` to crash the app when used
|
||||
* Add ``clock_to_timestamp`` API
|
||||
* Add ``clock_is_timezone_set`` API. In firmware 2.7, this function will always return false
|
||||
as timezone support is not yet implemented
|
||||
* Improve Bluetooth reliability
|
||||
* Fix bug showing 0% battery warning
|
||||
|
||||
### Changes for SDK Tools:
|
||||
No changes
|
||||
|
||||
### Changes for Examples:
|
||||
* Add [wakeup example]({{site.links.examples_org}}/feature-app-wakeup)
|
||||
|
||||
### Changes for Documentation:
|
||||
* Add ``Wakeup`` API documentation
|
||||
* Fix bug with missing ``snprintf`` specifier documentation
|
43
devsite/source/_changelogs/2.8.1.md
Normal file
43
devsite/source/_changelogs/2.8.1.md
Normal file
|
@ -0,0 +1,43 @@
|
|||
---
|
||||
# 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.8.1 - Changelog
|
||||
date: 2014-12-09
|
||||
---
|
||||
|
||||
This release fixes a number of bugs and improves BLE pairing on iOS.
|
||||
See [FW 2.8 Changelog](/sdk/changelogs/2.8/) for new features and major fixes.
|
||||
|
||||
## Detailed List of Changes:
|
||||
### Changes for Firmware:
|
||||
|
||||
* Fix bug that would cause the watch to crash when ``accel_data_service_unsubscribe`` was called in a `window_unload` handler
|
||||
* Revert error return values from ``resource_load_byte_range`` to pre-2.8 behavior
|
||||
* Speed up BLE pairing on iOS
|
||||
* Fix a bug that would cause an app to be built incorrectly if the first resource in appinfo.json was declared twice.
|
||||
* Reduce stack usage of resource handling to prevent stack overflows introduced in 2.8
|
||||
* Fix several strings in non-English languages
|
||||
* Fix bug in ``AppMessage`` that would cause the watch to crash
|
||||
|
||||
|
||||
### Changes for SDK Tools:
|
||||
|
||||
* Fix an issue where the SDK failed to build apps with non-ascii characters in the name.
|
||||
* Include locale.h in pebble.h
|
||||
|
||||
### Changes for Examples:
|
||||
No changes
|
||||
### Changes for Documentation:
|
||||
No changes
|
57
devsite/source/_changelogs/2.8.md
Normal file
57
devsite/source/_changelogs/2.8.md
Normal file
|
@ -0,0 +1,57 @@
|
|||
---
|
||||
# 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.8 - Changelog
|
||||
date: 2014-11-20
|
||||
---
|
||||
|
||||
This release changes the rendering behaviour of custom fonts in apps compiled with SDK 2.8. The change
|
||||
improves the visual appearance of fonts, but also causes them to be slightly larger. If you rebuild with
|
||||
SDK 2.8 and text no longer fits, you can revert to the old behaviour by setting `"compatibility": "2.7"`
|
||||
in the resource block for that font, like so:
|
||||
|
||||
```javascript
|
||||
{
|
||||
"type": "font",
|
||||
"file": "fonts/something.ttf",
|
||||
"name": "FONT_SOMETHING_24",
|
||||
"compatibility": "2.7"
|
||||
}
|
||||
```
|
||||
|
||||
System fonts are unaffected by this change.
|
||||
|
||||
## Detailed List of Changes:
|
||||
### Changes for Firmware:
|
||||
|
||||
* All system `GOTHIC` fonts are expanded to contain 351 characters
|
||||
* Add ``setlocale`` and ``i18n_get_system_locale`` APIs in preparation for internationalization support
|
||||
* Fix an issue that could cause an incorrect accelerometer sampling rate to be used
|
||||
* Fix an issue causing wakeup events scheduled less than thirty seconds in the future to fail
|
||||
* Improve the performance of very small resource reads
|
||||
* Fix an issue where iOS calendar alert notifications sometimes did not appear
|
||||
* Fix an issue sometimes causing spurious "Loading..." notifications to appear on iOS
|
||||
* Improve behaviour when trying to boot with a critically low battery
|
||||
|
||||
### Changes for SDK Tools:
|
||||
* Improve font rendering for custom fonts when compiling with SDK 2.8
|
||||
* This can change the font metrics. If the font no longer fits, add the flag `"compatibility": "2.7"`
|
||||
to the resource entry for that font.
|
||||
|
||||
### Changes for Examples:
|
||||
No changes
|
||||
|
||||
### Changes for Documentation:
|
||||
* Fix explanation of the timezone of timestamps passed to ``wakeup_schedule``
|
42
devsite/source/_changelogs/2.9.md
Normal file
42
devsite/source/_changelogs/2.9.md
Normal file
|
@ -0,0 +1,42 @@
|
|||
---
|
||||
# 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.9 - Changelog
|
||||
date: 2015-02-10
|
||||
---
|
||||
|
||||
This release introduces actionable notifications for Android and minor stability improvements.
|
||||
|
||||
## Detailed List of Changes:
|
||||
### Changes for Firmware:
|
||||
|
||||
* Add support for [Android actionable notifications](/blog/2014/12/19/Leverage-Android-Actionable-Notifications/)
|
||||
* Fix bug that caused crashes when ``mktime()`` was used
|
||||
* Fix behavior of ``window_stack_pop_all`` so that only the last window is animated
|
||||
* Compiler will now show an error when the resources limit is reached
|
||||
* Improve the stability of ``Worker``on launch
|
||||
* Fix bug where a ``Worker`` selected from the Activity menus would not be set to default
|
||||
* Fix bug where a ``Worker`` launched by a new app would not be set to default after the default worker was deleted
|
||||
* Fix an issue that caused ``AppMessage`` to report sends as failed when sending/recieving a high volume of messages
|
||||
* Notification date format is standardized: "Wednesday 11, February" -> "Wednesday, February 11"
|
||||
|
||||
### Changes for SDK Tools:
|
||||
No changes
|
||||
|
||||
### Changes for Examples:
|
||||
* Update openweather apis used in example apps.
|
||||
|
||||
### Changes for Documentation:
|
||||
No changes
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue