mirror of
https://github.com/EyeTrackVR/EyeTrackVR-Docs.git
synced 2025-09-26 23:09:15 +08:00
docs: new docs incoming
- add CI/CD - remove old docs files - begin finalizing new docs
This commit is contained in:
parent
8d8d026a45
commit
d976be6031
77
.github/workflows/build_release_vitepress.yml
vendored
Normal file
77
.github/workflows/build_release_vitepress.yml
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
name: Build and Deploy to Github Pages
|
||||
on:
|
||||
push:
|
||||
branches: [docs]
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
build:
|
||||
name: Build CodeBase
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Install dependencies
|
||||
uses: Borales/actions-yarn@v4.2.0
|
||||
with:
|
||||
cmd: install # will run `yarn install` command
|
||||
- name: Build project
|
||||
run: yarn build
|
||||
- name: Upload production-ready build files
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: production-files
|
||||
path: ./vitepress/docs/.vitepress/dist
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
name: Deploy
|
||||
needs: [build]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Create Directory
|
||||
run: mkdir -p dist
|
||||
- name: Download artifact
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: production-files
|
||||
path: dist/
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
- run: npm install -g conventional-changelog-conventionalcommits
|
||||
- run: npm install -g semantic-release@v19.0.5
|
||||
- run: npm install -g @semantic-release/exec
|
||||
- run: npm install -g @semantic-release/git
|
||||
- run: npm install -g @semantic-release/release-notes-generator
|
||||
- run: npm install -g @semantic-release/changelog
|
||||
- run: npm install -g @semantic-release/github
|
||||
- name: Release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: semantic-release
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./dist
|
||||
cleanup:
|
||||
name: Cleanup actions
|
||||
needs:
|
||||
- deploy
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: "♻️ remove build artifacts"
|
||||
uses: geekyeggo/delete-artifact@v1
|
||||
with:
|
||||
name: production-files
|
7
.gitignore
vendored
7
.gitignore
vendored
@ -9,4 +9,9 @@ node_modules
|
||||
.tmp
|
||||
.DS_Store
|
||||
.idea
|
||||
.vscode
|
||||
.vscode
|
||||
.temp
|
||||
cache
|
||||
.cache
|
||||
dist
|
||||
out
|
@ -148,8 +148,8 @@
|
||||
[
|
||||
"@semantic-release/exec",
|
||||
{
|
||||
"prepareCmd": "sed -i 's/\"version\": \"[0-9\\.]*\",/\"version\": \"${nextRelease.version}\",/g' ./NetworkManager/library.json",
|
||||
"publishCmd": "pio pkg publish --no-interactive"
|
||||
"prepareCmd": "sed -i 's/\"version\": \"[0-9\\.]*\",/\"version\": \"${nextRelease.version}\",/g' ./vitepress/package.json",
|
||||
"publishCmd": ""
|
||||
}
|
||||
],
|
||||
[
|
||||
@ -162,7 +162,7 @@
|
||||
"@semantic-release/git",
|
||||
{
|
||||
"assets": [
|
||||
"NetworkManager/library.json",
|
||||
"vitepress/package.json",
|
||||
"LICENSE*",
|
||||
"CHANGELOG.md"
|
||||
],
|
44
Gemfile
44
Gemfile
@ -1,44 +0,0 @@
|
||||
source "https://rubygems.org"
|
||||
# Hello! This is where you manage which Jekyll version is used to run.
|
||||
# When you want to use a different version, change it below, save the
|
||||
# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
|
||||
#
|
||||
# bundle exec jekyll serve
|
||||
#
|
||||
# This will help ensure the proper Jekyll version is running.
|
||||
# Happy Jekylling!
|
||||
gem "jekyll", "~> 3.9.0"
|
||||
# This is the default theme for new Jekyll sites. You may change this to anything you like.
|
||||
gem "just-the-docs"
|
||||
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
|
||||
# uncomment the line below. To upgrade, run `bundle update github-pages`.
|
||||
# gem "github-pages", group: :jekyll_plugins
|
||||
# If you have any plugins, put them here!
|
||||
group :jekyll_plugins do
|
||||
gem "jekyll-feed", "~> 0.12"
|
||||
# Jekyll SEO plugin
|
||||
gem "jekyll-seo-tag", "~> 2.1"
|
||||
# Jekyll Spaceship plugin
|
||||
gem "jekyll-spaceship"
|
||||
# Jekyll Sitemap plugin
|
||||
gem "jekyll-sitemap"
|
||||
# Jekyll Mermaid plugin
|
||||
gem "jekyll-mermaid"
|
||||
# Jekyll Remote Theme plugin
|
||||
gem "jekyll-remote-theme"
|
||||
|
||||
gem "kramdown-parser-gfm"
|
||||
end
|
||||
|
||||
# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
|
||||
# and associated library.
|
||||
platforms :mingw, :x64_mingw, :mswin, :jruby do
|
||||
gem "tzinfo", "~> 2.0.4"
|
||||
gem "tzinfo-data"
|
||||
end
|
||||
|
||||
# Performance-booster for watching directories on Windows
|
||||
gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin]
|
||||
|
||||
# GitHub page
|
||||
#gem "github-pages", "~> 221", group: :jekyll_plugins
|
@ -1,30 +0,0 @@
|
||||
---
|
||||
layout: default
|
||||
title: 404
|
||||
nav_exclude: true
|
||||
search_exclude: true
|
||||
has_children: false
|
||||
permalink: /404.html
|
||||
---
|
||||
|
||||
<style type="text/css" media="screen">
|
||||
.container {
|
||||
margin: 10px auto;
|
||||
max-width: 600px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 30px 0;
|
||||
font-size: 4em;
|
||||
line-height: 1;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container">
|
||||
<h1>404</h1>
|
||||
|
||||
<p><strong>Page not found 😔</strong></p>
|
||||
<p>The requested page could not be found.</p>
|
||||
</div>
|
@ -1,82 +0,0 @@
|
||||
|
||||
|
||||
## Step 15: Prepare to solder IR LED PCB V2s.
|
||||
Get your magnifying glass out, it's time to solder very smol things.
|
||||
|
||||
Gather 4 PCBs, 4 IR LEDs, and 2 ~700ohm resistors.
|
||||
|
||||
|
||||
698ohm resistors and V2 PCBs
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/WyoVdcR.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
|
||||
Here are the PCB pin-out labels:
|
||||
|
||||
V2
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/sNB6ju2.png" max-width="400" caption="" alt="img" %}
|
||||
|
||||
|
||||
LED labels:
|
||||
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/Ap8OAWY.png" max-width="400" caption="" alt="img" %}
|
||||
The green markings and notched corners mark the positive sides of the LEDs pictured above.
|
||||
|
||||
If you have different LEDs, please consult their datasheet.
|
||||
|
||||
Some terminology related to them:
|
||||
|
||||
5V: 5-volt power in.
|
||||
|
||||
GND: Ground or power out.
|
||||
|
||||
AR: After-Resistor this is to be used as the power in on the 2nd PCB in series as resistors are not needed on the 2nd PCB since they are on the 1st one.
|
||||
|
||||
SNG: Single resistor, use this as 5V in if you are using only 1 ~700ohm resistor on V3 boards (not recommended).
|
||||
|
||||
Negative: This marks the negative side of the LED.
|
||||
|
||||
Positive: This marks the positive side of the LED.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Step 17: Solder resistors on PCB V2.
|
||||
|
||||
You only need 1 PCB to have a resistor per eye.
|
||||
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/ayQ5vkf.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
Tin the resistor pads.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/DpFwecO.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
Hold the resistor in place.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/50ydMrl.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
Solder one end.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/Qq3cvxi.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
Flip to the other side of the resistor and solder it.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/yWGaKaC.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
|
||||
## Solder LEDs on PCB V2.
|
||||
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/Ql4zYCq.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
|
||||
Tin the pads
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/Xrczoyv.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
Place the resistor on the pads in the correct orientation.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/KKgP8qs.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
Solder each side of the resistor. Be careful not to solder at too high of a temp, recommended soldering temp is 230C with a max of 245C.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/SvbHAuY.jpg" max-width="400" caption="The LED is flipped in this Image, the green dot should face AWAY from the PCB." alt="img" %}
|
||||
|
||||
## Wire up the PCBs V2.
|
||||
|
||||
Basic full wiring diagram of IR PCBs V2
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/gopjVG3.png" max-width="500" caption="" alt="drawing" %}
|
||||
|
||||
The PCB that receives the 5V power is the one with the resistor. The second one, which gets its power from the ground pin of the first, does not have a resistor on it and its power input pin is the AR pin (After-Resistor). The 2nd PCBs ground pin goes to the ground of the system, in the diagram it is the ESPs ground pin.
|
@ -1,65 +0,0 @@
|
||||
[](https://github.com/RedHawk989/EyeTrackVR/issues) [](https://github.com/RedHawk989/EyeTrackVR/network) [](https://github.com/RedHawk989/EyeTrackVR/stargazers) [](https://github.com/redhawk989/EyeTrackVR/actions/workflows/build-jekyll.yml) [](https://github.com/redhawk989/EyeTrackVR/actions/workflows/pages/pages-build-deployment) 
|
||||
|
||||
- [EyeTrackVR](#eyetrackvr)
|
||||
- [This project is in development and is not fully finished](#this-project-is-in-development-and-is-not-fully-finished)
|
||||
- [Hardware](#hardware)
|
||||
- [About IR Emitter Safety](#about-ir-emitter-safety)
|
||||
- [Make sure you are using **NON-focused** emitters and at around ***5ma total power***](#make-sure-you-are-using-non-focused-emitters-and-at-around-5ma-total-power)
|
||||
- [Firmware](#firmware)
|
||||
- [Headset support](#headset-support)
|
||||
- [Contact](#contact)
|
||||
- [Licenses](#licenses)
|
||||
|
||||
# EyeTrackVR
|
||||
|
||||
Open source and *affordable* VR eye tracker platform for [VRChat](https://hello.vrchat.com/) via `OSC` and `UDP` protocol.
|
||||
|
||||
#### This project is in development and is not fully finished however, it is working for most users.
|
||||
|
||||
## Hardware
|
||||
|
||||
Please check out our [Parts list](https://redhawk989.github.io/EyeTrackVR/parts-list/) and our [full build guide](https://redhawk989.github.io/EyeTrackVR/full-build-guide/) along with our [hardware repo.](https://github.com/RedHawk989/EyeTrackVR-Hardware)
|
||||
|
||||
## About IR Emitter Safety
|
||||
|
||||
Please *exercise extreme caution* when messing around with IR emitters.
|
||||
<ins>Once safety testing has been completed links and files will be provided for the emitters</ins>. Please do not try to make, or use any emitters unless you know exactly what you are doing as it could be very harmful to your eyes if not done correctly.
|
||||
When files and resources are released <ins>**DO NOT BYPASS (OR NOT DO) ANY SAFETY FEATURES PUT IN PLACE**</ins>. This can result in irreversible bodily harm.
|
||||
The safety measures were put in place to REDUCE the potential failure risk. All further safety responsibilities are on the user. This includes visually checking with an IR camera that the brightness is correct and that you do not feel warmth or experience short-term effects after being exposed to the IR light (symptoms such as dark spots or dry/warm feeling eyes while actively using). While we strive to make EyeTrackVR as safe as possible, we do not hold any responsibility for damage done.
|
||||
|
||||
##### Make sure you are using **NON-focused** emitters and at around ***5ma total power***
|
||||
|
||||
[Effect of infrared radiation on the lens](./docs/Reference_Docs/saftey/effect_of_ir_on_the_lens.pdf)
|
||||
|
||||
[Training-library Nir Stds](./docs/Reference_Docs/saftey/training-library_nir_stds_20021011.pdf)
|
||||
|
||||
[AN002_Details on photobiological safety of LED light sources](./docs/Reference_Docs/saftey/AN002_Details_on_photobiological_safety_of_LED_light_sources.pdf)
|
||||
|
||||
## Firmware
|
||||
|
||||
Our firmware called OpenIris is made by `lorow` found [here](https://github.com/lorow/OpenIris).
|
||||
|
||||
## Headset support
|
||||
|
||||
Please take a look at our list of [3d printable mounts](https://redhawk989.github.io/EyeTrackVR/parts-list/#other-parts) and see if your headset is on the list.
|
||||
If it is not listed, It is recommended that you try to make a mount, or wait for a skilled community member to create one.
|
||||
|
||||
#### Contact
|
||||
|
||||
Please join our discord for updates and any questions.
|
||||
|
||||
[](https://discord.gg/kkXYbVykZX)
|
||||
|
||||
# Licenses
|
||||
|
||||
[](https://github.com/RedHawk989/EyeTrackVR/blob/main/LICENSE)
|
||||
|
||||
***All software is under the [MIT License](http://opensource.org/licenses/MIT).
|
||||
All documentation, including the [Wiki](https://github.com/RedHawk989/EyeTrackVR/wiki), is under the Creative Commons CC-BY-SA-4.0 license***.
|
||||
|
||||
<!-- <div align="center">
|
||||
<img src="./docs/assets/images/licenses/licenses.svg" width="300" alt="Open Licenses" />
|
||||
</div> -->
|
||||
|
||||
[Top](#eyetrackvr)
|
||||
|
@ -1 +0,0 @@
|
||||
Dir.glob('lib/tasks/*.rake').each {|r| import r}
|
108
docs/_config.yml
108
docs/_config.yml
@ -1,108 +0,0 @@
|
||||
title: 'EyeTrackVR Documentation'
|
||||
description: 'Documentation for EyeTrackVR, an Opensource and affordable VR eye tracker for VR Chat.'
|
||||
author: 'ZanzyTHEbar'
|
||||
email: info@h-bat.com
|
||||
url: "https://docs.eyetrackvr.dev"
|
||||
|
||||
# twitter_username:
|
||||
# facebook_username:
|
||||
github_username: RedHawk989
|
||||
|
||||
# Build settings
|
||||
remote_theme: just-the-docs/just-the-docs
|
||||
color_scheme: 'light'
|
||||
|
||||
heading_level: 6
|
||||
previews: 3
|
||||
|
||||
sass:
|
||||
style: compressed
|
||||
|
||||
baseurl: ''
|
||||
|
||||
favicon: "/assets/images/favicon.png" # the favicon for your site
|
||||
|
||||
permalink: pretty
|
||||
exclude:
|
||||
[
|
||||
'node_modules/',
|
||||
'*.gemspec',
|
||||
'*.gem',
|
||||
'gemfiles/',
|
||||
'Gemfile',
|
||||
'Gemfile.lock',
|
||||
'package.json',
|
||||
'package-lock.json',
|
||||
'script/',
|
||||
'LICENSE.txt',
|
||||
'lib/',
|
||||
'bin/',
|
||||
'Rakefile',
|
||||
'docs/tests/',
|
||||
'.sass-cache/',
|
||||
'.jekyll-cache/',
|
||||
'vendor/bundle/',
|
||||
'vendor/cache/',
|
||||
'vendor/gems/',
|
||||
'vendor/ruby/',
|
||||
]
|
||||
|
||||
plugins:
|
||||
- jekyll-feed
|
||||
- jekyll-seo-tag
|
||||
- jekyll-sitemap
|
||||
- jekyll-mermaid
|
||||
- jekyll-spaceship
|
||||
- jekyll-remote-theme
|
||||
|
||||
include: ['_pages', '_posts']
|
||||
timezone: "America/New_York"
|
||||
|
||||
# Search options
|
||||
search_enabled: true
|
||||
preview_words_before: 5
|
||||
preview_words_after: 10
|
||||
tokenizer_separator: /[\s/]+/
|
||||
rel_url: true
|
||||
button: true
|
||||
|
||||
# Links at the top of the page
|
||||
aux_links:
|
||||
'Discord':
|
||||
- '//discord.gg/kkXYbVykZX'
|
||||
'GitHub':
|
||||
- '//github.com/RedHawk989/EyeTrackVR'
|
||||
'Wiki':
|
||||
- '//github.com/RedHawk989/EyeTrackVR/wiki'
|
||||
|
||||
# Enable Back to Top bottom for all pages
|
||||
back_to_top: true
|
||||
back_to_top_text: "Top"
|
||||
|
||||
# Enable last edit timestamp for all pages
|
||||
last_edit_timestamp: true
|
||||
last_edit_time_format: "%b %e %Y at %I:%M %p"
|
||||
|
||||
# Sitemap options
|
||||
aux_links_new_tab: false # Whether to open aux_links in a new tab
|
||||
heading_anchors: true
|
||||
gh_edit_link: true # show or hide edit this page link
|
||||
gh_edit_link_text: 'Edit this page on GitHub.'
|
||||
gh_edit_repository: 'https://github.com/RedHawk989/EyeTrackVR' # the github URL for your repo
|
||||
gh_edit_branch: 'docs' # the branch that your docs is served from
|
||||
gh_edit_source: docs # the source that your files originate from
|
||||
gh_edit_view_mode: 'edit' # "tree" or "edit" if you want the user to jump into the editor immediately
|
||||
ga_tracking: UA-5555555-55 # Google Analytics tracking code - Dahl Winters please update this to your own code
|
||||
enableDNT: "false" # Enable Do-Not-Track
|
||||
ga_tracking_anonymize_ip: true # Use GDPR compliant Google Analytics settings (true by default)
|
||||
|
||||
# Google Forms configuration
|
||||
# comment-post: https://docs.google.com/forms/d/e/1FAIpQLScuqqkKDIUbPJpGfyLQJQe3mBNvQh45-eryzMWbqm7k7ALjGA
|
||||
# comment-read: https://docs.google.com/spreadsheets/d/1szz__qSlPZ5LmDlR9ovNqdSCOgoUAYCWg-gWwkCQlmw/
|
||||
# comment-post-fields: [entry.1141065141, entry.484163683, entry.231340692]
|
||||
google_forms_comments:
|
||||
google_app_script: https://script.google.com/macros/s/AKfycbyvN6BYATPrSahv5SpWKC44yu7GJmlVYyzl6HZeDlYZI5T6PJ5HuF2IMGvTO7E4cA34ng/exec
|
||||
recaptcha_site_key: 6LcOgsQfAAAAAF1GB4ENB-qwe8vdtsqbHS1duIeV
|
||||
chunked_comment_loading: true
|
||||
lazy_load_comments: true
|
||||
comment_replies_enabled: true
|
@ -1,76 +0,0 @@
|
||||
---
|
||||
# Use this YAML file to create a list of supported hmds and 3d parts for them.
|
||||
|
||||
- hmd: "Quest 2"
|
||||
parts:
|
||||
- ""
|
||||
hyper_links:
|
||||
- url: "https://github.com/RedHawk989/EyeTrackVR-Hardware/blob/main/3d_Printed_Mounts/Quest_2/Arkfall/EyeTrack_Quest_2_Mount_v10_By_Arkfall.stl"
|
||||
desc: "Camera and IR emitter mount by Arkfall"
|
||||
|
||||
- url: "https://github.com/RedHawk989/EyeTrackVR-Hardware/blob/main/3d_Printed_Mounts/Quest_2/Prohurtz/EyeTrack_Arkfall_Quest_2_Mount_Edit_By_Prourtz.stl"
|
||||
desc: "Camera and IR emitter mount by Prohurtz"
|
||||
|
||||
- url: "https://github.com/RedHawk989/EyeTrackVR-Hardware/blob/main/3d_Printed_Mounts/Quest_2/Arkfall/Quest_2_ESP_Mount_v2_By_Arkfall.stl"
|
||||
desc: "ESP mount by Arkfall"
|
||||
|
||||
- url: "https://github.com/RedHawk989/EyeTrackVR-Hardware/blob/main/3d_Printed_Mounts/Quest_2/Prohurtz/Quest_2_ESP_Mounts_By_Prohurtz.stl"
|
||||
desc: "ESP mount by Prohurtz"
|
||||
|
||||
threed_link_id: 1
|
||||
|
||||
- hmd: "Valve Index"
|
||||
parts:
|
||||
- "ESP mount : N/A"
|
||||
hyper_links:
|
||||
- url: "https://github.com/RedHawk989/EyeTrackVR-Hardware/tree/main/3d_Printed_Mounts/Valve_Index/Seaweed"
|
||||
desc: "High IPD compatible Camera and IR emitter mount by Seaweed"
|
||||
|
||||
- url: "https://github.com/RedHawk989/EyeTrackVR-Hardware/tree/main/3d_Printed_Mounts/Valve_Index/qdot"
|
||||
desc: "Camera and IR emitter mount by Qdot"
|
||||
|
||||
- url: "https://github.com/rrazgriz/IndexEyeTrackVR/tree/main/hardware"
|
||||
desc: "Camera mount by Razgriz"
|
||||
|
||||
- url: "https://github.com/MUTEtheCyberwolf/VALVE-INDEX-DEV-Frunk-1.0/tree/main/3D%20Print%20Files%20STL(Ascii)"
|
||||
desc: "ESP frunk mod by MUTE the Cyberwolf"
|
||||
|
||||
threed_link_id: 2
|
||||
|
||||
- hmd: "Samsung Odyssey +"
|
||||
parts:
|
||||
- "ESP mount : Refer to general ESP Mounts"
|
||||
hyper_links:
|
||||
- url: "https://github.com/RedHawk989/EyeTrackVR-Hardware/blob/main/3d_Printed_Mounts/Samsung_Odyssey%2B/Breakdown/Samsung%20Odyssey%2B%20Left%20by%20Breakdown.stl"
|
||||
desc: "Camera and IR emitter mount by Breakdown"
|
||||
|
||||
threed_link_id: 3
|
||||
|
||||
- hmd: "Quest 1"
|
||||
parts:
|
||||
- "ESP mount : Refer to general ESP Mounts"
|
||||
hyper_links:
|
||||
- url: "https://github.com/RedHawk989/EyeTrackVR-Hardware/blob/main/3d_Printed_Mounts/Quest_1/G0LDJAY/Quest_1_Cam_mount_v5_By_G0LDJAY.stl"
|
||||
desc: "Camera and IR emitter mount by G0LDJAY"
|
||||
|
||||
threed_link_id: 4
|
||||
|
||||
- hmd: "Vive Pro 2"
|
||||
parts:
|
||||
- "ESP mount : Refer to general ESP Mounts"
|
||||
hyper_links:
|
||||
- url: "https://github.com/RedHawk989/EyeTrackVR-Hardware/tree/main/3d_Printed_Mounts/Vive_Pro_2/StormFox"
|
||||
desc: "Camera and IR emitter mount by StormFox"
|
||||
|
||||
threed_link_id: 5
|
||||
|
||||
- hmd: "General ESP Mounts"
|
||||
parts:
|
||||
- ""
|
||||
hyper_links:
|
||||
- url: "https://github.com/RedHawk989/EyeTrackVR-Hardware/blob/main/3d_Printed_Mounts/General_ESP32-CAM_Mounts/ESPCAMshellv7_by_G0LDJAY.stl"
|
||||
desc: "ESP mount by G0LDJAY for general HMD use (use if there are no specific HMD mounts available)"
|
||||
|
||||
threed_link_id: 6
|
||||
---
|
||||
|
@ -1,43 +0,0 @@
|
||||
tip: '<div class="alert alert-success" role="alert"><i class="fa fa-check-square-o"></i> <b>Tip: </b>'
|
||||
note: '<div class="alert alert-info" role="alert"><i class="fa fa-info-circle"></i> <b>Note: </b>'
|
||||
important: '<div class="alert alert-warning" role="alert"><i class="fa fa-warning"></i> <b>Important: </b>'
|
||||
warning: '<div class="alert alert-danger" role="alert"><i class="fa fa-exclamation-circle"></i> <b>Warning: </b>'
|
||||
end: "</div>"
|
||||
|
||||
callout_danger: '<div class="bs-callout bs-callout-danger">'
|
||||
callout_default: '<div class="bs-callout bs-callout-default">'
|
||||
callout_primary: '<div class="bs-callout bs-callout-primary">'
|
||||
callout_success: '<div class="bs-callout bs-callout-success">'
|
||||
callout_info: '<div class="bs-callout bs-callout-info">'
|
||||
callout_warning: '<div class="bs-callout bs-callout-warning">'
|
||||
|
||||
hr_faded: '<hr class="faded"/>'
|
||||
hr_shaded: '<hr class="shaded"/>'
|
||||
|
||||
# A work in progress
|
||||
|
||||
# To use these, add the following to a file:
|
||||
#
|
||||
# {{site.data.alerts_alternative.note}}
|
||||
# {{site.data.alerts_alternative.tip}}
|
||||
# {{site.data.alerts_alternative.important}}
|
||||
# {{site.data.alerts_alternative.warning}}
|
||||
# {{site.data.alerts_alternative.callout_danger}}
|
||||
# {{site.data.alerts_alternative.callout_default}}
|
||||
# {{site.data.alerts_alternative.callout_primary}}
|
||||
# {{site.data.alerts_alternative.callout_success}}
|
||||
# {{site.data.alerts_alternative.callout_info}}
|
||||
# {{site.data.alerts_alternative.callout_warning}}
|
||||
# {{site.data.alerts_alternative.hr_faded}}
|
||||
# {{site.data.alerts_alternative.hr_shaded}}
|
||||
#
|
||||
# Example of a note with code:
|
||||
#
|
||||
# {{site.data.alerts_alternative.note}}
|
||||
# <p>This is a note with code:</p>
|
||||
# <pre>
|
||||
# def foo(x): <br>
|
||||
# return x+1
|
||||
# </pre>
|
||||
# {{site.data.alerts.end}}
|
||||
#
|
@ -1,76 +0,0 @@
|
||||
---
|
||||
# Use this YAML file to create a list of FAQ questions and answers.
|
||||
|
||||
- question: "What is the goal of this project?"
|
||||
answer: "To provide an open source, affordable VR eyetracker for Socail games like VRChat as well as provide an open eyetracking platform."
|
||||
hyper_link: ""
|
||||
link_description: ""
|
||||
type: "general"
|
||||
faq_link_id: 1
|
||||
|
||||
- question: "What headsets will be supported?"
|
||||
answer: "Any headset that the hardware can fit in with community mounts or a mount you design."
|
||||
hyper_link: ""
|
||||
link_description: ""
|
||||
type: "general"
|
||||
faq_link_id: 2
|
||||
|
||||
- question: "How will this work?"
|
||||
answer: "Currently, a camera is mounted inside the headset for each eye. The camera streams through wifi to a PC client which processes and sends eye tracking data to an OSC endpoint ex VRChat."
|
||||
hyper_link: ""
|
||||
link_description: ""
|
||||
type: "general"
|
||||
faq_link_id: 3
|
||||
|
||||
- question: "What features will be supported?"
|
||||
answer: "The goal is eye tracking with eye openness, and some form of pupil dilation. A far away aspiration of this project is some form of weak foveated rendering because it's cool and any small performance increase in VR is welcome."
|
||||
hyper_link: ""
|
||||
link_description: ""
|
||||
type: "general"
|
||||
faq_link_id: 4
|
||||
|
||||
- question: "When will this be completed?"
|
||||
answer: "When it's done 😉 I have a semi busy life so development may slow and speed up inconsistently."
|
||||
hyper_link: ""
|
||||
link_description: ""
|
||||
type: "general"
|
||||
faq_link_id: 5
|
||||
|
||||
- question: "Will IR damage my eyes?"
|
||||
answer: "This project has safety in mind. If you do all of the safety measures that we put into place and visually test the amount of IR light you will be fine. Please note we have not finished development of all safety stuff so be careful, aaaa ."
|
||||
hyper_link: "https://dammedia.osram.info/media/bin/osram-dam-2496608/AN002_Details%20on%20photobiological%20safety%20of%20LED%20light%20sources.pdf"
|
||||
link_description: " here is a pdf with safety information"
|
||||
type: "general"
|
||||
faq_link_id: 6
|
||||
|
||||
- question: "How expensive will this be?"
|
||||
answer: "My goal is to keep it as cheap as possible with around $75 as the absolute max, with current setups being around $25-40. aaaa"
|
||||
hyper_link: ""
|
||||
link_description: ""
|
||||
type: "general"
|
||||
faq_link_id: 7
|
||||
|
||||
- question: "How do I set up my avatar?"
|
||||
answer: "Check out the VR Chat face tracking wiki on our github. Keep in mind that we currently only support float parameters. "
|
||||
hyper_link: ""
|
||||
link_description: ""
|
||||
type: "general"
|
||||
faq_link_id: 8
|
||||
|
||||
- question: "What hardware does this use?/How do I build?"
|
||||
answer: "Testing is still being done to validate our current hardware choice, no hardware has been fully confirmed therefore I cannot recommend you buy parts and assemble one yourself unless you are good with losing money and are going to be actively contributing to the project. This stands true still as of 5/3."
|
||||
hyper_link: ""
|
||||
link_description: ""
|
||||
type: "general"
|
||||
faq_link_id: 9
|
||||
|
||||
- question: "Where are the docs?"
|
||||
answer: "All of our documentation is located on this website, all future documentation will be found here as well."
|
||||
hyper_link: ""
|
||||
link_description: ""
|
||||
type: "general"
|
||||
faq_link_id: 10
|
||||
|
||||
---
|
||||
|
||||
# https://github.com/benaclejames/VRCFaceTracking/wiki
|
@ -1,22 +0,0 @@
|
||||
---
|
||||
# Use this YAML file to create a list of Contributors
|
||||
|
||||
- name: qdot
|
||||
github: qdot
|
||||
linkedin:
|
||||
twitter: qDot
|
||||
description: 'Created the initial version of the GUI App'
|
||||
|
||||
- name: dfgHiatus
|
||||
github: dfgHiatus
|
||||
linkedin:
|
||||
twitter:
|
||||
description: 'Created NeosVR mod'
|
||||
|
||||
- name:
|
||||
github:
|
||||
linkedin:
|
||||
twitter:
|
||||
description:
|
||||
---
|
||||
|
@ -1,9 +0,0 @@
|
||||
---
|
||||
# Use this YAML file to create a list of Key Credits
|
||||
|
||||
- name: SlimeVR
|
||||
url: https://docs.slimevr.dev
|
||||
description: "Thank you to the SlimeVR Team for their design inspirations as we began building out the documentation."
|
||||
|
||||
---
|
||||
|
@ -1,29 +0,0 @@
|
||||
---
|
||||
# Use this YAML file to create a list of Key Members
|
||||
|
||||
- name: Prohurtz
|
||||
github: RedHawk989
|
||||
linkedin:
|
||||
twitter: Prohurtz_
|
||||
description: 'Initiator / Moderator / Documentor / Lead Software Developer'
|
||||
|
||||
- name: Summer
|
||||
github: SummerSigh
|
||||
linkedin:
|
||||
twitter: TheGoodAI1
|
||||
description: 'Machine Learning Engineer / Data Scientist / Developer'
|
||||
|
||||
- name: lorow
|
||||
github: lorow
|
||||
linkedin:
|
||||
twitter: JustALorow
|
||||
description: 'Lead Firmware Developer / Developer'
|
||||
|
||||
- name: DaOfficialWizard
|
||||
github: ZanzyTHEbar
|
||||
linkedin:
|
||||
twitter:
|
||||
description: 'Firmware Developer / Documentation Manager / Developer'
|
||||
|
||||
---
|
||||
|
@ -1,51 +0,0 @@
|
||||
<style>
|
||||
#cookie-notice {
|
||||
padding: 0.5rem 1rem;
|
||||
display: none;
|
||||
text-align: center;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
background: #27262b;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
#cookie-notice a {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
#cookie-notice span {
|
||||
display: block;
|
||||
padding-top: 3px;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
#cookie-notice a {
|
||||
position: relative;
|
||||
bottom: 4px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<div id="cookie-notice">
|
||||
<span>I would like to use third party cookies and scripts to improve the functionality of this
|
||||
website.
|
||||
</span>
|
||||
<a id="cookie-notice-accept" class="btn btn-primary btn-sm">Approve</a>
|
||||
<a href="/EyeTrackVR/privacy" class="btn btn-primary btn-sm">More info
|
||||
</a>
|
||||
</div>
|
||||
<script>
|
||||
if (readCookie('cookie-notice-dismissed') == 'true') {
|
||||
{% include ga.js %}
|
||||
} else {
|
||||
document.getElementById('cookie-notice').style.display = 'block';
|
||||
}
|
||||
document.getElementById('cookie-notice-accept').addEventListener("click", function () {
|
||||
createCookie('cookie-notice-dismissed', 'true', 31);
|
||||
document.getElementById('cookie-notice').style.display = 'none';
|
||||
location.reload();
|
||||
});
|
||||
</script>
|
@ -1 +0,0 @@
|
||||
@import "./custom/custom";
|
@ -1,7 +0,0 @@
|
||||
{% if site.logo %}
|
||||
$logo: "{{ site.logo | absolute_url }}";
|
||||
{% endif %}
|
||||
@import "./support/support";
|
||||
@import "./color_schemes/{{ include.color_scheme }}";
|
||||
@import "./modules";
|
||||
{% include css/custom.scss.liquid %}
|
@ -1,102 +0,0 @@
|
||||
<!-- Do not edit this file - it is a template. Please edit the threed_parts.yml file -->
|
||||
<style>
|
||||
.accordion {
|
||||
width: 100%;
|
||||
margin: 1px auto;
|
||||
padding: 5px 5px;
|
||||
}
|
||||
|
||||
.accordion .container {
|
||||
position: relative;
|
||||
margin: 5px 5px;
|
||||
}
|
||||
|
||||
/* Positions the labels relative to the .container. Adds padding to the top and bottom and increases font size. Also makes its cursor a pointer */
|
||||
.accordion .hmd {
|
||||
position: relative;
|
||||
padding: 5px 0;
|
||||
font-size: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Positions the plus sign 5px from the right. Centers it using the transform property. */
|
||||
.accordion .hmd::before {
|
||||
content: '\2304';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: -5px;
|
||||
font-size: 30px;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
/* Hides the content (height: 0), decreases font size, justifies text and adds transition */
|
||||
.accordion .parts {
|
||||
position: relative;
|
||||
height: 0;
|
||||
font-size: 20px;
|
||||
text-align: justify;
|
||||
width: 100%;
|
||||
transition: 0.5s;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Adds a horizontal line between the contents */
|
||||
.accordion hr {
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
border: 1px solid grey;
|
||||
}
|
||||
|
||||
/* Unhides the content part when active. Sets the height */
|
||||
.accordion .container.active .parts {
|
||||
height: 180px;
|
||||
}
|
||||
|
||||
/* Changes from plus sign to negative sign once active */
|
||||
.accordion .container.active .hmd::before {
|
||||
content: '';
|
||||
font-size: 30px;
|
||||
}
|
||||
</style>
|
||||
<h1 class="fs-6 fw-500" align="left">3d Printed Parts For Supported Headsets</h1>
|
||||
<div class="accordion-body">
|
||||
{% for threed_parts in site.data.3d_printed_parts_yaml.3d_printed_parts %}
|
||||
<div class="accordion">
|
||||
<hr>
|
||||
<div class="container">
|
||||
<div class="hmd fw-400">
|
||||
<h1 class="fs-5 fw-500">
|
||||
{{ threed_parts.hmd }}
|
||||
</h1>
|
||||
</div>
|
||||
<div class="parts">
|
||||
<blockquote>
|
||||
<span class="answerspan-{{ threed_parts.threed_parts_link_id }}">
|
||||
<ul>
|
||||
{% if threed_parts.hyper_links != null and threed_parts.hyper_links != "" %}
|
||||
{% for hyper_link in threed_parts.hyper_links %}
|
||||
<p>
|
||||
<a href="{{ hyper_link.url }}" target="_blank">{{ hyper_link.desc }}</a>
|
||||
</p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% for part in threed_parts.parts %}
|
||||
<li>{{ part }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</span>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
const accordion = document.getElementsByClassName('container');
|
||||
|
||||
for (i = 0; i < accordion.length; i++) {
|
||||
accordion[i].addEventListener('click', function () {
|
||||
this.classList.toggle('active');
|
||||
})
|
||||
}
|
||||
</script>
|
@ -1,91 +0,0 @@
|
||||
<style>
|
||||
.accordion-{{ include.type }} {
|
||||
width: 100%;
|
||||
margin: 1px auto;
|
||||
padding: 5px 5px;
|
||||
}
|
||||
|
||||
.accordion-{{ include.type }} .accordion-container {
|
||||
position: relative;
|
||||
margin: 5px 5px;
|
||||
}
|
||||
|
||||
/* Positions the labels relative to the .container. Adds padding to the top and bottom and increases font size. Also makes its cursor a pointer */
|
||||
.accordion-{{ include.type }} .question-{{ include.type }} {
|
||||
position: relative;
|
||||
padding: 5px 0;
|
||||
font-size: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Positions the plus sign 5px from the right. Centers it using the transform property. */
|
||||
.accordion-{{ include.type }} .question-{{ include.type }}::before {
|
||||
content: '\2304';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 5px;
|
||||
font-size: 30px;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
/* Hides the content (height: 0), decreases font size, justifies text and adds transition */
|
||||
.accordion-{{ include.type }} .answer-{{ include.type }} {
|
||||
position: relative;
|
||||
height: 0;
|
||||
font-size: 20px;
|
||||
text-align: justify;
|
||||
width: 100%;
|
||||
transition: 0.5s;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Adds a horizontal line between the contents */
|
||||
.accordion-{{ include.type }} hr {
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
border: 1px solid grey;
|
||||
}
|
||||
|
||||
/* Unhides the content part when active. Sets the height */
|
||||
.accordion-{{ include.type }} .accordion-container.active .answer-{{ include.type }} {
|
||||
height: 180px;
|
||||
}
|
||||
|
||||
/* Changes from plus sign to negative sign once active */
|
||||
.accordion-{{ include.type }} .accordion-container.active .question{{ include.type }}::before {
|
||||
content: '';
|
||||
font-size: 30px;
|
||||
}
|
||||
</style>
|
||||
<div class="accordion-body-{{ include.type }}">
|
||||
{% for faq in site.data.faq_yaml.frequently_asked_questions %}
|
||||
{% if faq.type == include.type %}
|
||||
{% if faq.question != null and faq.question != "" %}
|
||||
<div class="accordion-{{ include.type }}">
|
||||
<hr>
|
||||
<div class="accordion-container" onclick=" this.classList.toggle('active');">
|
||||
<div class="question-{{ include.type }} fw-400">
|
||||
<h1 class="fs-5 fw-500">
|
||||
{{ faq.question }}
|
||||
</h1>
|
||||
</div>
|
||||
<div class="answer-{{ include.type }}">
|
||||
<blockquote>
|
||||
<span class="answerspan{{ faq.faq_link_id }}">
|
||||
{% capture editable_part %}
|
||||
<a href="{{ faq.hyper_link }}" target="_blank">{{ faq.link_description }}</a>
|
||||
{% endcapture %}
|
||||
{% if faq.answer contains 'aaaa ' %}
|
||||
{{ faq.answer | replace: 'aaaa ', editable_part }}
|
||||
{% else %}
|
||||
{{ faq.answer }}
|
||||
{% endif %}
|
||||
</span>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
@ -1,19 +0,0 @@
|
||||
<!-- Custom Alert Using an SVG -->
|
||||
<!-- DO NOT FORMAT THIS DOCUMENT -->
|
||||
<blockquote>
|
||||
<p>
|
||||
<span class="icon-span-info"><svg class="octicon octicon-info mr-2" viewBox="0 0 16 16" version="1.1" width="16"
|
||||
height="16" aria-hidden="true">
|
||||
<path fill-rule="evenodd"
|
||||
d="M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8zm6.5-.25A.75.75 0 017.25 7h1a.75.75 0 01.75.75v2.75h.25a.75.75 0 010 1.5h-2a.75.75 0 010-1.5h.25v-2h-.25a.75.75 0 01-.75-.75zM8 6a1 1 0 100-2 1 1 0 000 2z">
|
||||
</path>
|
||||
</svg><b>Info:</b>
|
||||
<p class="fs-5 fw-300">
|
||||
{{ include.content }}
|
||||
{% if include.hyper_link != null && include.hyper_link != "" %}
|
||||
<a href="{{ include.hyper_link }}" target="_blank">{{ include.description }}</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
</span>
|
||||
</p>
|
||||
</blockquote>
|
@ -1,19 +0,0 @@
|
||||
<!-- Custom Alert Using an SVG -->
|
||||
<!-- DO NOT FORMAT THIS DOCUMENT -->
|
||||
<blockquote>
|
||||
<p>
|
||||
<span class="icon-span-info"><svg class="octicon octicon-info mr-2" viewBox="0 0 16 16" version="1.1" width="16"
|
||||
height="16" aria-hidden="true">
|
||||
<path fill-rule="evenodd"
|
||||
d="M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8zm6.5-.25A.75.75 0 017.25 7h1a.75.75 0 01.75.75v2.75h.25a.75.75 0 010 1.5h-2a.75.75 0 010-1.5h.25v-2h-.25a.75.75 0 01-.75-.75zM8 6a1 1 0 100-2 1 1 0 000 2z">
|
||||
</path>
|
||||
</svg><b>Info:</b>
|
||||
<p class="fs-5 fw-300">
|
||||
{{ include.content }}
|
||||
{% if include.hyper_link != null && include.hyper_link != "" %}
|
||||
<a href="{{ include.hyper_link }}" target="_blank">{{ include.description }}</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
</span>
|
||||
</p>
|
||||
</blockquote>
|
@ -1,28 +0,0 @@
|
||||
<!-- Custom Alert Using an SVG -->
|
||||
<!-- DO NOT FORMAT OR EDIT THIS DOCUMENT -->
|
||||
<blockquote>
|
||||
<p>
|
||||
<span class="icon-span-note"><svg class="octicon octicon-note mr-2" viewBox="0 0 16 16" version="1.1" width="16"
|
||||
height="16" aria-hidden="true">
|
||||
<path fill-rule="evenodd"
|
||||
d="M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8zm6.5-.25A.75.75 0 017.25 7h1a.75.75 0 01.75.75v2.75h.25a.75.75 0 010 1.5h-2a.75.75 0 010-1.5h.25v-2h-.25a.75.75 0 01-.75-.75zM8 6a1 1 0 100-2 1 1 0 000 2z">
|
||||
</path>
|
||||
</svg><b>Note:</b>
|
||||
{% if include.content.size > 150 %}
|
||||
<p class="fs-3 fw-300">
|
||||
{{ include.content }}
|
||||
{% if include.hyper_link != null && include.hyper_link != "" %}
|
||||
<a href="{{ include.hyper_link }}" target="_blank">{{ include.description }}</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
{% else %}
|
||||
<small class="fs-3 fw-300">
|
||||
{{ include.content }}
|
||||
{% if include.hyper_link != null && include.hyper_link != "" %}
|
||||
<a href="{{ include.hyper_link }}" target="_blank">{{ include.description }}</a>
|
||||
{% endif %}
|
||||
</small>
|
||||
{% endif %}
|
||||
</span>
|
||||
</p>
|
||||
</blockquote>
|
@ -1,16 +0,0 @@
|
||||
<!-- Custom Alert Using an SVG -->
|
||||
<!-- DO NOT FORMAT THIS DOCUMENT -->
|
||||
<blockquote>
|
||||
<p>
|
||||
<span class="icon-span-success"><span class="iconify-inline" data-icon="icon-park-solid:success" data-width="16"
|
||||
data-height="16"></span><b> Success:</b>
|
||||
<p class="fs-5 fw-300">
|
||||
{{ include.content }}
|
||||
{% if include.hyper_link != null && include.hyper_link != "" %}
|
||||
<a href="{{ include.hyper_link }}" target="_blank">{{ include.description }}</a>
|
||||
{% endif %}
|
||||
|
||||
</p>
|
||||
</span>
|
||||
</p>
|
||||
</blockquote>
|
@ -1,16 +0,0 @@
|
||||
<!-- Custom Alert Using an SVG -->
|
||||
<!-- DO NOT FORMAT THIS DOCUMENT -->
|
||||
<blockquote>
|
||||
<p>
|
||||
<span class="icon-span-tip"><span class="iconify octicon octicon-tip mr-2"
|
||||
data-icon="fa:check-square-o"></span><b>Tip:</b>
|
||||
<p class="fs-5 fw-300">
|
||||
{{ include.content }}
|
||||
{% if include.hyper_link != null && include.hyper_link != "" %}
|
||||
<a href="{{ include.hyper_link }}" target="_blank">{{ include.description }}</a>
|
||||
{% endif %}
|
||||
|
||||
</p>
|
||||
</span>
|
||||
</p>
|
||||
</blockquote>
|
@ -1,19 +0,0 @@
|
||||
<!-- Custom Alert Using an SVG -->
|
||||
<!-- DO NOT EDIT THIS DOCUMENT -->
|
||||
<blockquote>
|
||||
<p>
|
||||
<span class="icon-span-warning"><svg class="octicon octicon-alert mr-2" viewBox="0 0 16 16" version="1.1"
|
||||
width="16" height="16" aria-hidden="true">
|
||||
<path fill-rule="evenodd"
|
||||
d="M8.22 1.754a.25.25 0 00-.44 0L1.698 13.132a.25.25 0 00.22.368h12.164a.25.25 0 00.22-.368L8.22 1.754zm-1.763-.707c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0114.082 15H1.918a1.75 1.75 0 01-1.543-2.575L6.457 1.047zM9 11a1 1 0 11-2 0 1 1 0 012 0zm-.25-5.25a.75.75 0 00-1.5 0v2.5a.75.75 0 001.5 0v-2.5z">
|
||||
</path>
|
||||
</svg><b>Warning:</b>
|
||||
<p class="fs-5 fw-300">
|
||||
{{ include.content }}
|
||||
{% if include.hyper_link != null && include.hyper_link != "" %}
|
||||
<a href="{{ include.hyper_link }}" target="_blank">{{ include.description }}</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
</span>
|
||||
</p>
|
||||
</blockquote>
|
@ -1,73 +0,0 @@
|
||||
<style>
|
||||
/* Customize the label (the container) */
|
||||
.custom-checkbox-container {
|
||||
display: block;
|
||||
position: relative;
|
||||
padding-left: 35px;
|
||||
margin-bottom: 12px;
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* Hide the browser's default checkbox */
|
||||
.custom-checkbox-container input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
height: 0;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
/* Create a custom checkbox */
|
||||
.custom-checkbox-checkmark {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 25px;
|
||||
width: 25px;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
/* On mouse-over, add a grey background color */
|
||||
.custom-checkbox-container:hover input~.custom-checkbox-checkmark {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
input[type="checkbox"]:checked {
|
||||
background-color: #3899ff;
|
||||
|
||||
}
|
||||
|
||||
input[type="checkbox"]:checked:after {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Create the checkmark/indicator (hidden when not checked) */
|
||||
.custom-checkbox-checkmark:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Style the checkmark/indicator */
|
||||
.custom-checkbox-container .custom-checkbox-checkmark:after {
|
||||
left: 9px;
|
||||
top: 5px;
|
||||
width: 5px;
|
||||
height: 10px;
|
||||
border: solid white;
|
||||
border-width: 0 3px 3px 0;
|
||||
-webkit-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
</style>
|
||||
<div class="custom-checkbox">
|
||||
<label class="custom-checkbox-container">{{ include.label }}
|
||||
<input type="custom-checkbox-checkbox" checked="{{ include.checked }}">
|
||||
<span class="custom-checkbox-checkmark"></span>
|
||||
</label>
|
||||
</div>
|
@ -1,72 +0,0 @@
|
||||
<style>
|
||||
/* Customize the label (the container) */
|
||||
.custom-checkbox-container {
|
||||
display: block;
|
||||
position: relative;
|
||||
padding-left: 35px;
|
||||
margin-bottom: 12px;
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* Hide the browser's default radio button */
|
||||
.custom-checkbox-container input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
height: 0;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
/* Create a custom radio button */
|
||||
.custom-checkbox-radiobutton {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 25px;
|
||||
width: 25px;
|
||||
background-color: #eee;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
/* On mouse-over, add a grey background color */
|
||||
.custom-checkbox-container:hover input~.custom-checkbox-radiobutton {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
/* When the radio button is checked, add a blue background */
|
||||
.custom-checkbox-container input:checked~.custom-checkbox-radiobutton {
|
||||
background-color: #2196F3;
|
||||
}
|
||||
|
||||
/* Create the indicator (the dot/circle - hidden when not checked) */
|
||||
.custom-checkbox-radiobutton:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Show the indicator (dot/circle) when checked */
|
||||
.custom-checkbox-container input:checked~.custom-checkbox-radiobutton:after {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Style the indicator (dot/circle) */
|
||||
.custom-checkbox-container .custom-checkbox-radiobutton:after {
|
||||
top: 9px;
|
||||
left: 9px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: white;
|
||||
}
|
||||
</style>
|
||||
<div class="custom-radiobutton">
|
||||
<label class="custom-checkbox-container">{{ include.label }}
|
||||
<input type="custom-checkbox-radiobutton" checked="{{ include.checked }}">
|
||||
<span class="custom-checkbox-radiobutton"></span>
|
||||
</label>
|
||||
</div>
|
@ -1,4 +0,0 @@
|
||||
<figure class="image">
|
||||
<img src="{{ include.url }}" alt="{{ include.description }}">
|
||||
<figcaption>{{ include.description }}</figcaption>
|
||||
</figure>
|
@ -1,17 +0,0 @@
|
||||
<div align="center">
|
||||
<figure>
|
||||
{% if include.url %}
|
||||
<a class="no_icon" target="_blank" rel="noopener" href="{{ include.url }}">
|
||||
{% endif %}
|
||||
<img class="docimage" src="{{ include.url }}" alt="{{ include.alt }}" {% if include.max-width %} style="max-width: {{ include.max-width }}px" {% endif %} />
|
||||
{% if include.url %}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if include.caption %}
|
||||
<figcaption>
|
||||
<br>
|
||||
{{ include.caption }}
|
||||
</figcaption>
|
||||
{% endif %}
|
||||
</figure>
|
||||
</div>
|
@ -1 +0,0 @@
|
||||
<img class="inline" src="images/{{include.file}}" alt="{{include.alt}}" />
|
@ -1,987 +0,0 @@
|
||||
{%- comment -%}
|
||||
This section is to determine whether or not chunked comment loading is enabled.
|
||||
By default this is turned ON. If the page has enabled or disabled this feature explicitly,
|
||||
the individual page value is used. Otherwise the site's value, if any, is used.
|
||||
{%- endcomment -%}
|
||||
{%- assign chunked_loading_enabled = true -%}
|
||||
{%- if page.chunked_comment_loading == false -%}
|
||||
{%- assign chunked_loading_enabled = false -%}
|
||||
{%- else -%}
|
||||
{%- if site.google_forms_comments.chunked_comment_loading == false and page.chunked_comment_loading != true -%}
|
||||
{%- assign chunked_loading_enabled = false -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
|
||||
{%- comment -%}
|
||||
This section is to determine whether or not lazy loading of the comments is enabled.
|
||||
By default this is turned OFF. If the page has enabled or disabled this feature explicitly,
|
||||
the individual page value is used. Otherwise the site's value, if any, is used.
|
||||
{%- endcomment -%}
|
||||
{%- assign lazy_load_enabled = false -%}
|
||||
{%- if page.lazy_load_comments == true -%}
|
||||
{%- assign lazy_load_enabled = true -%}
|
||||
{%- elsif site.google_forms_comments.lazy_load_comments == true -%}
|
||||
{%- unless page.lazy_load_comments == false -%}
|
||||
{%- assign lazy_load_enabled = true -%}
|
||||
{%- endunless -%}
|
||||
{%- endif -%}
|
||||
|
||||
{%- comment -%}
|
||||
This section is to determine whether or recaptcha is enabled.
|
||||
{%- endcomment -%}
|
||||
{%- assign recaptcha_enabled = false -%}
|
||||
{%- if site.google_forms_comments.recaptcha_site_key -%}
|
||||
{%- assign recaptcha_enabled = true -%}
|
||||
{%- endif -%}
|
||||
|
||||
|
||||
{%- comment -%}
|
||||
This section is to determine whether or comment replies are enabled.
|
||||
{%- endcomment -%}
|
||||
{%- assign comment_replies_enabled = false -%}
|
||||
{%- if site.google_forms_comments.comment_replies_enabled == true -%}
|
||||
{%- assign comment_replies_enabled = true -%}
|
||||
{%- endif -%}
|
||||
|
||||
|
||||
{%- if site.comment-read or site.google_forms_comments.google_app_script -%}
|
||||
<script>
|
||||
|
||||
{%- comment -%}
|
||||
Helper functions used so that we can forego using jQuery
|
||||
functions. When appscripts is enabled, this allows us to
|
||||
get rid of the jQuery dependency (for comments) altogether.
|
||||
{%- endcomment -%}
|
||||
function setText(elementId, textContent) {
|
||||
document.getElementById(elementId).textContent = textContent;
|
||||
};
|
||||
|
||||
function show(elementId) {
|
||||
document.getElementById(elementId).style.display = 'inline';
|
||||
};
|
||||
|
||||
function hide(elementId) {
|
||||
document.getElementById(elementId).style.display = 'none';
|
||||
};
|
||||
|
||||
function getValue(elementId) {
|
||||
return document.getElementById(elementId).value;
|
||||
};
|
||||
|
||||
function setValue(elementId, value) {
|
||||
return document.getElementById(elementId).value = value;
|
||||
};
|
||||
|
||||
function fadeIn(element) {
|
||||
var duration = 400;
|
||||
element.style.opacity = 0;
|
||||
let opacity = 0;
|
||||
const timer = setInterval(function() {
|
||||
opacity += 50 / duration;
|
||||
if (opacity >= 1) {
|
||||
clearInterval(timer);
|
||||
opacity = 1;
|
||||
}
|
||||
element.style.opacity = opacity;
|
||||
}, 50);
|
||||
};
|
||||
|
||||
|
||||
function disableButtonWithLoader(elementId) {
|
||||
var buttonToDisable = document.getElementById(elementId);
|
||||
if (buttonToDisable == null) {
|
||||
return;
|
||||
}
|
||||
buttonToDisable.disabled = true;
|
||||
setText(elementId, "\xa0");
|
||||
}
|
||||
|
||||
function disablePostCommentButton() {
|
||||
disableButtonWithLoader("comment-submit");
|
||||
};
|
||||
|
||||
function enablePostCommentButton() {
|
||||
var postCommentButton = document.getElementById("comment-submit");
|
||||
postCommentButton.disabled = false;
|
||||
setText("comment-submit", "Post");
|
||||
};
|
||||
|
||||
|
||||
{%- comment -%}
|
||||
/* Load Required 3rd-Party Scripts. We use the following:
|
||||
- jquery for DOM manipulation
|
||||
- jquery-csv for parsing Google Sheets CSV data to JSON
|
||||
- validator for escaping user-entered comments to prevent malicious code input in comments
|
||||
Make sure to update these to the latest versions every once in a while. */
|
||||
{%- endcomment -%}
|
||||
|
||||
{%- comment -%}
|
||||
/* Initial load of the comments section contnet. This ensures that we are only loading
|
||||
JQuery and other scripts once we actually need them */
|
||||
{%- endcomment -%}
|
||||
async function initialCommentLoad() {
|
||||
disableButtonWithLoader("load-comment-button");
|
||||
{%- unless site.google_forms_comments.google_app_script -%}
|
||||
{%- comment -%}
|
||||
/* Load JQuery */
|
||||
{%- endcomment -%}
|
||||
var loadJquery = document.createElement("script");
|
||||
loadJquery.type = "text/javascript";
|
||||
loadJquery.src = "https://code.jquery.com/jquery-3.6.0.min.js";
|
||||
document.head.appendChild(loadJquery);
|
||||
{%- endunless -%}
|
||||
|
||||
{%- if recaptcha_enabled -%}
|
||||
{%- comment -%}
|
||||
/* Load Recaptcha */
|
||||
{%- endcomment -%}
|
||||
var loadRecaptcha = document.createElement("script");
|
||||
loadRecaptcha.src = "https://www.google.com/recaptcha/api.js?render={{ site.google_forms_comments.recaptcha_site_key }}";
|
||||
document.head.appendChild(loadRecaptcha);
|
||||
{%- endif -%}
|
||||
|
||||
{%- comment -%}
|
||||
/* Load Validator (to ensure we don't run code from comments for example) */
|
||||
{%- endcomment -%}
|
||||
var loadValidator = document.createElement("script");
|
||||
loadValidator.src = "https://cdnjs.cloudflare.com/ajax/libs/validator/13.5.2/validator.min.js";
|
||||
document.head.appendChild(loadValidator);
|
||||
|
||||
{%- comment -%}
|
||||
/* Await Scripts Loaded */
|
||||
{%- endcomment -%}
|
||||
{%- if recaptcha_enabled -%}
|
||||
await loadRecaptcha.onload;
|
||||
{%- endif -%}
|
||||
await loadValidator.onload;
|
||||
|
||||
{%- if site.google_forms_comments.google_app_script -%}
|
||||
reloadComments();
|
||||
{%- else -%}
|
||||
loadJquery.onload = function() {
|
||||
{%- comment -%}
|
||||
/* We need to ensure that jQuery is ready before we can load JQuery CSV (used for .csv parsing) */
|
||||
{%- endcomment -%}
|
||||
async function checkJQuery() {
|
||||
if (typeof jQuery === "undefined") {
|
||||
return false;
|
||||
} else {
|
||||
clearTimeout(interval);
|
||||
|
||||
{%- comment -%}
|
||||
/* Load JQuery CSV (need regular JQuery first) */
|
||||
{%- endcomment -%}
|
||||
var loadJqueryCsv = document.createElement("script");
|
||||
loadJqueryCsv.src = "https://cdnjs.cloudflare.com/ajax/libs/jquery-csv/1.0.11/jquery.csv.min.js";
|
||||
document.head.appendChild(loadJqueryCsv);
|
||||
|
||||
{%- comment -%}
|
||||
/* Wait for JQuery CSV to finish loading */
|
||||
{%- endcomment -%}
|
||||
await loadJqueryCsv.onload;
|
||||
|
||||
{%- comment -%}
|
||||
/* Now, load the comments */
|
||||
{%- endcomment -%}
|
||||
reloadComments();
|
||||
}
|
||||
};
|
||||
{%- comment -%}
|
||||
/* check if JQuery is ready every 250 MS
|
||||
this timer will be cleared after the check passes */
|
||||
{%- endcomment -%}
|
||||
var interval = setInterval(checkJQuery, 250);
|
||||
};
|
||||
{%- endif -%}
|
||||
};
|
||||
|
||||
var thisPageUrl = "{{ page.url }}";
|
||||
const EXTRA_INFO_START = "chunkedCommentInfoStart";
|
||||
const EXTRA_INFO_END = "chunkedCommentInfoEnd";
|
||||
|
||||
{%- comment -%}
|
||||
/* Visbile comments are those already dislayed to the user.
|
||||
Hidden comments are those that are already retrieved from Google Sheets but not shown yet (i.e. with a load more button visible).
|
||||
Net new comments are those that have been added since the comment submit button was pressed. Usually this will be the single added
|
||||
comment. */
|
||||
{%- endcomment -%}
|
||||
var visibleComments = [];
|
||||
var hiddenComments = [];
|
||||
var netNewComments = [];
|
||||
{%- if comment_replies_enabled -%}
|
||||
var commentIds = new Set();
|
||||
{%- endif -%}
|
||||
|
||||
{%- comment -%}
|
||||
/* Format the comment's date to our desired format */
|
||||
{%- endcomment -%}
|
||||
function formatDate(stringDate) {
|
||||
var date = new Date(stringDate);
|
||||
var dateOptions = { year: 'numeric', month: 'long', day: 'numeric'};
|
||||
var timeOptions = { hour: 'numeric', minute: 'numeric' };
|
||||
return `${date.toLocaleDateString("en-us", dateOptions)} at ${date.toLocaleTimeString("en-us", timeOptions)}`;
|
||||
};
|
||||
|
||||
{%- comment -%}
|
||||
/* Called when the comments have been loaded or relaoded.
|
||||
Comments that we have already displayed on the page will be ignored */
|
||||
{%- endcomment -%}
|
||||
async function displayComments(comments) {
|
||||
show("comments-and-input");
|
||||
hide("load-comments");
|
||||
var hasVisibleComments = visibleComments.length > 0;
|
||||
|
||||
{%- comment -%}
|
||||
/* if we have no comments, show the 'no comments available' section */
|
||||
{%- endcomment -%}
|
||||
if (comments == null || comments === "" || comments == []) {
|
||||
if (!hasVisibleComments) {
|
||||
show("no-comments");
|
||||
hide("load-more-comments");
|
||||
hide("num-comments-displayed");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
{%- if comment_replies_enabled -%}
|
||||
commentIds = new Set();
|
||||
{%- endif -%}
|
||||
|
||||
{%- if site.google_forms_comments.google_app_script -%}
|
||||
var newHiddenComments = comments
|
||||
{%- if comment_replies_enabled -%}
|
||||
.map(item => {
|
||||
commentIds.add(Date.parse(item.timestamp)?.toString());
|
||||
return item;
|
||||
})
|
||||
{%- endif -%}
|
||||
.sort((a, b) => (new Date(a.timestamp).getTime() || 0) - (new Date(b.timestamp).getTime() || 0))
|
||||
.map(item => JSON.stringify(item));
|
||||
{%- else -%}
|
||||
{%- comment -%}
|
||||
/* Add headers so json objects are named properly */
|
||||
{%- endcomment -%}
|
||||
comments = `timestamp,name,comment,isAuthor\n${comments}`;
|
||||
var newHiddenComments = $.csv.toObjects(comments)
|
||||
{%- if comment_replies_enabled -%}
|
||||
.map(item => {
|
||||
commentIds.add(Date.parse(item.timestamp)?.toString());
|
||||
return item;
|
||||
})
|
||||
{%- endif -%}
|
||||
.sort((a, b) => (new Date(a.timestamp).getTime() || 0) - (new Date(b.timestamp).getTime() || 0))
|
||||
.map(item => JSON.stringify(item));
|
||||
{%- endif -%}
|
||||
|
||||
if (hasVisibleComments) {
|
||||
netNewComments = newHiddenComments
|
||||
.filter(item => !visibleComments.includes(item))
|
||||
.filter(item => !hiddenComments.includes(item));
|
||||
}
|
||||
|
||||
hiddenComments = newHiddenComments
|
||||
.filter(item => !visibleComments.includes(item))
|
||||
.filter(item => !netNewComments.includes(item));
|
||||
|
||||
loadMoreComments(false || !hasVisibleComments);
|
||||
};
|
||||
|
||||
{%- comment -%}
|
||||
/* Loads more comments if there are any left to display from those already loaded from the server */
|
||||
{%- endcomment -%}
|
||||
function loadMoreComments(isLoadMoreAction) {
|
||||
{%- if chunked_loading_enabled -%}
|
||||
var newCommentsToDisplay = hiddenComments.slice(-5);
|
||||
{%- else -%}
|
||||
var newCommentsToDisplay = hiddenComments;
|
||||
{%- endif -%}
|
||||
|
||||
if (isLoadMoreAction) {
|
||||
{%- comment -%}
|
||||
/* iterate over each comment that came from Google Sheets */
|
||||
{%- endcomment -%}
|
||||
newCommentsToDisplay.reverse().forEach(element => displaySingleComment(element, true));
|
||||
hiddenComments = hiddenComments.filter(item => !newCommentsToDisplay.includes(item) && !visibleComments.includes(item));
|
||||
} else {
|
||||
{%- comment -%}
|
||||
/* add the new comments if there are any */
|
||||
{%- endcomment -%}
|
||||
netNewComments.forEach(element => displaySingleComment(element, false));
|
||||
netNewComments = []
|
||||
}
|
||||
|
||||
setText("num-comments-displayed", `Showing ${visibleComments.length} of ${visibleComments.length + hiddenComments.length} comments`);
|
||||
|
||||
if (hiddenComments.length == 0) {
|
||||
hide("load-more-comments");
|
||||
} else {
|
||||
show("load-more-comments");
|
||||
}
|
||||
};
|
||||
|
||||
{%- if comment_replies_enabled -%}
|
||||
var currentFadeItem = null;
|
||||
|
||||
function fadeColor(element) {
|
||||
if (currentFadeItem != null) {
|
||||
clearInterval(currentFadeItem);
|
||||
currentFadeItem = null;
|
||||
}
|
||||
|
||||
var duration = 1000;
|
||||
var step = 25;
|
||||
let opacity = 1;
|
||||
const timer = setInterval(function() {
|
||||
opacity -= (1 / (duration / step));
|
||||
if (opacity <= 0) {
|
||||
clearInterval(timer);
|
||||
currentFadeItem = null;
|
||||
opacity = 0;
|
||||
}
|
||||
element.style.background = "rgba(3, 155, 229, "+ opacity +")";
|
||||
}, step);
|
||||
currentFadeItem = timer;
|
||||
};
|
||||
|
||||
function smoothScrollTo(element) {
|
||||
element.scrollIntoView({
|
||||
behavior: "smooth",
|
||||
block: "start",
|
||||
inline: "nearest"
|
||||
});
|
||||
};
|
||||
|
||||
function jumpToComment(commentId) {
|
||||
var element = document.getElementsByClassName("" + commentId)[0];
|
||||
while(element == null && hiddenComments.length > 0) {
|
||||
loadMoreComments(true);
|
||||
element = document.getElementsByClassName("" + commentId)[0];
|
||||
}
|
||||
if (element != null) {
|
||||
smoothScrollTo(element);
|
||||
fadeColor(element);
|
||||
}
|
||||
};
|
||||
|
||||
function clearCommentReplyItem() {
|
||||
document.getElementById("comment-reply-info").innerHTML = ``;
|
||||
};
|
||||
|
||||
function replyToComment(commentId) {
|
||||
document.getElementById("comment-reply-info").innerHTML = `<small class="comment-reply-clear" onclick="clearCommentReplyItem()">Ⓧ </small><small onClick="jumpToComment('${commentId}')">Replying to comment <a id="reply-to-comment-id">${commentId}</a></small>`;
|
||||
smoothScrollTo(document.getElementsByClassName("comments-form")[0]);
|
||||
};
|
||||
{%- endif -%}
|
||||
|
||||
function getCommentInfo(comment) {
|
||||
var extraCommentInfo = comment?.match(EXTRA_INFO_START + ".+" + EXTRA_INFO_END);
|
||||
return {
|
||||
text : comment?.replace(extraCommentInfo, ""),
|
||||
extraCommentInfo : JSON.parse(extraCommentInfo?.toString()?.replace(EXTRA_INFO_START, "")?.replace(EXTRA_INFO_END, "") ?? "{}")
|
||||
};
|
||||
};
|
||||
|
||||
function displaySingleComment(element, isPrepend) {
|
||||
{%- comment -%}
|
||||
/* don't re-add existing comments */
|
||||
{%- endcomment -%}
|
||||
if (visibleComments.includes(element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var jsonElement = JSON.parse(element);
|
||||
var comment = getCommentInfo(jsonElement.comment);
|
||||
{%- comment -%}
|
||||
/* If the author was the one who commented back, add this 'verified' logic */
|
||||
{%- endcomment -%}
|
||||
var verifiedAuthorTag = "";
|
||||
if (jsonElement.isAuthor == true || jsonElement.isAuthor === "TRUE") {
|
||||
verifiedAuthorTag = " <strong>(Author)</strong>";
|
||||
}
|
||||
{%- comment -%}
|
||||
/* Create the new item using HTML and append it to the user-visible comment section */
|
||||
{%- endcomment -%}
|
||||
var newItem = document.createElement("div");
|
||||
newItem.classList.add("comment-item");
|
||||
{%- if comment_replies_enabled -%}
|
||||
newItem.classList.add("reply-item");
|
||||
var commentReplyId = "" + Date.parse(jsonElement.timestamp);
|
||||
newItem.classList.add(commentReplyId);
|
||||
var replyToHtml = null;
|
||||
var replyId = comment?.extraCommentInfo?.replyToCommentId;
|
||||
if (replyId != null && replyId != "" && commentIds.has(replyId)) {
|
||||
replyToHtml = `<p class="comment-reply-id" onclick="jumpToComment('${replyId}')"><<< ${replyId}</p>`;
|
||||
}
|
||||
var currentCommentReplyButton = `<span class="comment-reply-button" onclick="replyToComment(${commentReplyId})"><img />Reply</span>`;
|
||||
{%- endif -%}
|
||||
|
||||
newItem.innerHTML = `
|
||||
<p class="commenter-name">${validator.escape(jsonElement.name.toString())}${verifiedAuthorTag}
|
||||
<small>${formatDate(jsonElement.timestamp)}
|
||||
{%- if comment_replies_enabled -%}
|
||||
${currentCommentReplyButton ?? ""}
|
||||
{%- endif -%}
|
||||
</small>
|
||||
</p>
|
||||
<div>
|
||||
{%- if comment_replies_enabled -%}
|
||||
${replyToHtml ?? ""}
|
||||
{%- endif -%}
|
||||
<p>${validator.escape(comment?.text?.toString()).replace(new RegExp('\r?\n','g'), '<br />')}</p>
|
||||
</div>
|
||||
`.trim();
|
||||
if (isPrepend) {
|
||||
document.getElementById("comment-container").prepend(newItem);
|
||||
} else {
|
||||
document.getElementById("comment-container").append(newItem);
|
||||
}
|
||||
fadeIn(newItem);
|
||||
visibleComments.push(element);
|
||||
|
||||
{%- comment -%}
|
||||
/* Hide the 'no comments available' section since we have added a comment */
|
||||
{%- endcomment -%}
|
||||
hide("no-comments");
|
||||
show("num-comments-displayed");
|
||||
};
|
||||
|
||||
{%- if site.google_forms_comments.google_app_script -%}
|
||||
function reloadComments() {
|
||||
fetch(`{{ site.google_forms_comments.google_app_script }}?url=${thisPageUrl}`)
|
||||
.then(response => response.json())
|
||||
.then(response => {
|
||||
var error = response?.error || null;
|
||||
if (error != null) {
|
||||
console.error(error);
|
||||
setText("comment-submit-error", error);
|
||||
show("comment-submit-error");
|
||||
} else {
|
||||
setText("comment-submit-error", '');
|
||||
hide("comment-submit-error");
|
||||
displayComments(response);
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
{%- else -%}
|
||||
{%- comment -%}
|
||||
/* Calls to the Google Sheets gviz API to load the comment data
|
||||
Since we are storing comments for all of our blog articles in one sheet, we filter
|
||||
by page URL. */
|
||||
{%- endcomment -%}
|
||||
function reloadComments() {
|
||||
{%- comment -%}
|
||||
/*
|
||||
Use SQL in the gviz URL to load the correct csv.
|
||||
In this implementation, columns are mapped to the following:
|
||||
A - timestamp, the time the comment was left
|
||||
B - page url, the page the comment was left on
|
||||
C - name, the text left in the comment name field
|
||||
D - comment, the text left in the comment field
|
||||
E - isAuthor, boolean indicating if the comment was left by the actual author
|
||||
*/
|
||||
{%- endcomment -%}
|
||||
var sqlStatement = encodeURIComponent(`SELECT A, C, D, E WHERE B = '${thisPageUrl}'`);
|
||||
fetch(`{{ site.comment-read }}/gviz/tq?tqx=out:csv&sheet=comments&tq=${sqlStatement}&headers=0`)
|
||||
.then(response => response.text())
|
||||
.then(response => displayComments(response));
|
||||
};
|
||||
{%- endif -%}
|
||||
|
||||
{%- comment -%}
|
||||
/* encodes the form data for http transport */
|
||||
{%- endcomment -%}
|
||||
const encodeFormData = (data) => {
|
||||
return Object.keys(data)
|
||||
.map(key => encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))
|
||||
.join('&');
|
||||
};
|
||||
|
||||
{%- if recaptcha_enabled -%}
|
||||
function checkRecaptcha() {
|
||||
{%- comment -%}
|
||||
Disallow posting a new comment until this one has posted or failed.
|
||||
{%- endcomment -%}
|
||||
disablePostCommentButton();
|
||||
grecaptcha.ready(function() {
|
||||
var pageAction = "comment_submit_{{ page.title }}".replace(/[^A-Za-z/_]/g, "");
|
||||
grecaptcha.execute('{{ site.google_forms_comments.recaptcha_site_key }}', { action: pageAction }).then(function(token) {
|
||||
postComment(token);
|
||||
});
|
||||
});
|
||||
return false;
|
||||
};
|
||||
{%- endif -%}
|
||||
|
||||
|
||||
function getCommentContent() {
|
||||
var comment = getValue("comment-comment")?.toString();
|
||||
|
||||
var extraCommentInfo = {};
|
||||
|
||||
{%- if comment_replies_enabled -%}
|
||||
var replyToCommentId = document?.getElementById("reply-to-comment-id")?.text;
|
||||
if (replyToCommentId != null && replyToCommentId != "") {
|
||||
extraCommentInfo.replyToCommentId = replyToCommentId;
|
||||
}
|
||||
{%- endif -%}
|
||||
|
||||
if (Object.keys(extraCommentInfo).length !== 0) {
|
||||
comment = EXTRA_INFO_START + JSON.stringify(extraCommentInfo) + EXTRA_INFO_END + comment;
|
||||
}
|
||||
|
||||
return comment;
|
||||
};
|
||||
|
||||
{%- comment -%}
|
||||
/* Posts a comment */
|
||||
{%- endcomment -%}
|
||||
{%- if site.google_forms_comments.google_app_script -%}
|
||||
function postComment(recaptchaToken) {
|
||||
disablePostCommentButton();
|
||||
var username = getValue("comment-name");
|
||||
var comment = getCommentContent();
|
||||
|
||||
fetch(`{{ site.google_forms_comments.google_app_script }}`, {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
redirect: "follow",
|
||||
headers: {
|
||||
"Content-Type": "text/plain;charset=utf-8"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
url : thisPageUrl?.toString(),
|
||||
name : username?.toString(),
|
||||
comment : comment?.toString(),
|
||||
recaptchaToken: (recaptchaToken || null)
|
||||
})
|
||||
}).then(response => response.json())
|
||||
.then(response => {
|
||||
var error = response?.error || null;
|
||||
if (error != null) {
|
||||
console.error(error);
|
||||
setText("comment-submit-error", error);
|
||||
show("comment-submit-error");
|
||||
} else {
|
||||
setValue("comment-name", '');
|
||||
setValue("comment-comment", '');
|
||||
setText("comment-submit-error", '');
|
||||
hide("comment-submit-error");
|
||||
displayComments(response);
|
||||
{%- if comment_replies_enabled -%}
|
||||
clearCommentReplyItem();
|
||||
{%- endif -%}
|
||||
}
|
||||
})
|
||||
.catch(error => {console.log(error);})
|
||||
.finally(() => { enablePostCommentButton(); });
|
||||
|
||||
return false;
|
||||
};
|
||||
{%- else -%}
|
||||
function postComment(recaptchaToken) {
|
||||
disablePostCommentButton();
|
||||
var username = getValue("comment-name");
|
||||
var comment = getCommentContent();
|
||||
|
||||
fetch(`{{ site.comment-post }}/formResponse`, {
|
||||
method: 'POST',
|
||||
mode: 'no-cors',
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
},
|
||||
body: encodeFormData({
|
||||
"{{ site.comment-post-fields[0] }}" : thisPageUrl?.toString(),
|
||||
"{{ site.comment-post-fields[1] }}" : username?.toString(),
|
||||
"{{ site.comment-post-fields[2] }}" : comment?.toString()
|
||||
})
|
||||
}).then(response => {
|
||||
setValue("comment-name", '');
|
||||
setValue("comment-comment", '');
|
||||
{%- if comment_replies_enabled -%}
|
||||
clearCommentReplyItem();
|
||||
{%- endif -%}
|
||||
reloadComments();
|
||||
})
|
||||
.catch(error => {console.log(error);})
|
||||
.finally(() => { enablePostCommentButton(); });
|
||||
|
||||
return false;
|
||||
};
|
||||
{%- endif -%}
|
||||
|
||||
{%- unless lazy_load_enabled -%}
|
||||
initialCommentLoad();
|
||||
{%- endunless -%}
|
||||
</script>
|
||||
{%- comment -%}
|
||||
<!--
|
||||
HTML for displaying the actual comment section.
|
||||
It has a state for both when the article has comments and when it does not. -->
|
||||
{%- endcomment -%}
|
||||
<h4 class="post-subtitle">Comments</h4>
|
||||
<div id="load-comments" class="comments">
|
||||
<button id="load-comment-button" class="comment-button" onclick="initialCommentLoad()">Load Comments</button>
|
||||
</div>
|
||||
<div id="comments-and-input">
|
||||
<div id="comment-section" class="comments">
|
||||
<p id="num-comments-displayed"></p>
|
||||
<button id="load-more-comments" class="comment-button" onclick="loadMoreComments(true)" type="button">Load Older Comments</button>
|
||||
<div id="no-comments" class="comment-info-text">
|
||||
<p>There are currently no comments on this article, be the first to add one below</p>
|
||||
</div>
|
||||
<div id="comment-container"></div>
|
||||
</div>
|
||||
<h4 class="post-subtitle">Add a Comment</h4>
|
||||
<div class="comments">
|
||||
<div class="comment-info-text">
|
||||
<p>Note that we may remove comments for any reason, so try to be civil. If you are looking for a response to your comment, either leave your email address or check back on this page periodically.</p>
|
||||
{%- if site.google_forms_comments.google_app_script -%}
|
||||
<p id="comment-submit-error"></p>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
<div class="comments-form">
|
||||
{%- if recaptcha_enabled -%}
|
||||
<form onsubmit="return checkRecaptcha()" id="comment-form" autocomplete="off">
|
||||
{%- else -%}
|
||||
<form onsubmit="return postComment()" id="comment-form" autocomplete="off">
|
||||
{%- endif -%}
|
||||
<ul>
|
||||
<li>
|
||||
<input id="comment-name" name="username" type="text" placeholder="Name" required="" value="">
|
||||
{%- if comment_replies_enabled -%}
|
||||
<p id="comment-reply-info"></p>
|
||||
{%- endif -%}
|
||||
</li>
|
||||
<li><textarea id="comment-comment" name="comment" placeholder="Comment" required=""></textarea></li>
|
||||
<li><button id="comment-submit" type="submit" class="comment-button">Post</button></li>
|
||||
</ul>
|
||||
|
||||
{%- if recaptcha_enabled -%}
|
||||
<p id="comment-recaptcha-disclaimer">This site is protected by reCAPTCHA and the Google
|
||||
<a href="https://policies.google.com/privacy">Privacy Policy</a> and
|
||||
<a href="https://policies.google.com/terms">Terms of Service</a> apply.
|
||||
{%- endif -%}
|
||||
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{%- comment -%}
|
||||
<!--
|
||||
Styling information.
|
||||
This might typically be in an scss file but is added here so only a single
|
||||
file needs to be added to a project trying to implement this feature. -->
|
||||
{%- endcomment -%}
|
||||
<style>
|
||||
@import url("https://fonts.googleapis.com/css?family=Source+Sans+Pro");
|
||||
.comment-item {
|
||||
position: relative;
|
||||
padding: 0.5em 2.5em;
|
||||
background: white;
|
||||
color: black;
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
width: 95%;
|
||||
margin: 1em auto;
|
||||
box-shadow: 2px 2px 12px 1px rgba(8, 8, 8, 0.5);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.comment-item:after {
|
||||
content: "";
|
||||
position: relative;
|
||||
display: block;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.comment-item p {
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.comment-item small {
|
||||
padding-left: 0.7em;
|
||||
color: #999;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.commenter-name {
|
||||
color: #367588;
|
||||
text-decoration: none;
|
||||
font-size: 1em;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.commenter-name strong {
|
||||
color: #e91e63;
|
||||
text-decoration: none;
|
||||
font-size: 1em;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
{%- if comment_replies_enabled -%}
|
||||
.comment-reply-button {
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.comment-reply-button img {
|
||||
display: inline;
|
||||
vertical-align: middle;
|
||||
width: 1.2em;
|
||||
height: 1.2em;
|
||||
margin: 0;
|
||||
content:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 0 24 24' width='24px' fill='%23999999'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M10 9V5l-7 7 7 7v-4.1c5 0 8.5 1.6 11 5.1-1-5-4-10-11-11z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.comment-reply-button:hover {
|
||||
color: #e91e63;
|
||||
}
|
||||
|
||||
.comment-reply-button:hover img {
|
||||
content:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 0 24 24' width='24px' fill='%23e91e63'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M10 9V5l-7 7 7 7v-4.1c5 0 8.5 1.6 11 5.1-1-5-4-10-11-11z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.comment-reply-id {
|
||||
color: #e91e63;
|
||||
font-size: .9em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#comment-reply-info {
|
||||
float: right;
|
||||
font-size: .9em;
|
||||
color: #e91e63;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#comment-reply-info small {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.comment-reply-clear {
|
||||
color: #e91e63;
|
||||
font-size: 1.1em;
|
||||
cursor: pointer;
|
||||
}
|
||||
{%- endif -%}
|
||||
|
||||
#comment-reply-info p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.comments-form {
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
width: 95%;
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
}
|
||||
|
||||
.comments-form ul {
|
||||
list-style: none !important;
|
||||
margin-left: -40px;
|
||||
}
|
||||
|
||||
.comments-form ul li {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.comments {
|
||||
align-items: center;
|
||||
border-top: 0.5px solid #e5e5e5;
|
||||
padding-top: 1rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.comment-button {
|
||||
border: 0;
|
||||
border-radius: 8px;
|
||||
background: #6f55d5;
|
||||
color: #fff;
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
font-weight: bold;
|
||||
font-size: 0.9em;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 20px;
|
||||
outline-style: none;
|
||||
padding: 10px 20px;
|
||||
/* box-shadow: 2px 2px 4px 1px rgba(8, 8, 8, 0.5); */
|
||||
box-shadow: rgba(50, 50, 93, 0.25) 0px 50px 100px -20px, rgba(0, 0, 0, 0.3) 0px 30px 60px -30px, rgba(10, 37, 64, 0.35) 0px -2px 6px 0px inset;
|
||||
width: auto;
|
||||
min-width: 25%;
|
||||
transition-duration: 0.4s;
|
||||
}
|
||||
|
||||
.comment-button:hover {
|
||||
background-color: #6f55d5;
|
||||
background-image: linear-gradient(#6f55d5, #5739ce);
|
||||
}
|
||||
|
||||
.comment-button:active {
|
||||
background-color: #5739ce;
|
||||
background-image: linear-gradient(#5739ce, #6f55d5);
|
||||
box-shadow: rgba(50, 50, 93, 0.25) 0px 30px 60px -12px inset, rgba(0, 0, 0, 0.3) 0px 18px 36px -18px inset;
|
||||
}
|
||||
|
||||
#comment-submit {
|
||||
width: auto;
|
||||
min-width: 25%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.comment-button:disabled::after,
|
||||
.comment-button[disabled]::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
border: 4px solid transparent;
|
||||
border-top-color: #ffffff;
|
||||
border-radius: 50%;
|
||||
-webkit-animation: button-loading-spinner 1s ease infinite;
|
||||
animation: button-loading-spinner 1s ease infinite;
|
||||
}
|
||||
|
||||
@keyframes button-loading-spinner {
|
||||
from {
|
||||
transform: rotate(0turn);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(1turn);
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes button-loading-spinner {
|
||||
from {
|
||||
transform: rotate(0turn);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(1turn);
|
||||
}
|
||||
}
|
||||
|
||||
#load-more-comments {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#load-more-comments,
|
||||
#num-comments-displayed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#comment-name,
|
||||
#comment-comment {
|
||||
width: 50%;
|
||||
padding: 10px;
|
||||
border: 0;
|
||||
border-radius: 8px;
|
||||
background: #f7f7f7;
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
}
|
||||
|
||||
#comment-name::-webkit-input-placeholder,
|
||||
#comment-comment::-webkit-input-placeholder {
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
}
|
||||
|
||||
#comment-name::-moz-placeholder,
|
||||
#comment-comment::-moz-placeholder {
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
}
|
||||
|
||||
#comment-name:-ms-input-placeholder,
|
||||
#comment-comment:-ms-input-placeholder {
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
}
|
||||
|
||||
#comment-name::-ms-input-placeholder,
|
||||
#comment-comment::-ms-input-placeholder {
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
}
|
||||
|
||||
#comment-name::placeholder,
|
||||
#comment-comment::placeholder {
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
}
|
||||
|
||||
#comment-name:focus,
|
||||
#comment-comment:focus {
|
||||
background: #fff;
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
}
|
||||
|
||||
#comment-comment {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
resize: vertical;
|
||||
min-height: 80px;
|
||||
}
|
||||
|
||||
{%- if recaptcha_enabled -%}
|
||||
{%- comment -%}
|
||||
If you want to use the regular recaptcha badge (instead of the text currently below
|
||||
the submit button), remove this and the text disclaimer in the HTML above. Note that
|
||||
according to their FAQ page, one or the other must be displayed.
|
||||
https://developers.google.com/recaptcha/docs/faq#id-like-to-hide-the-recaptcha-badge.-what-is-allowed
|
||||
{%- endcomment -%}
|
||||
.grecaptcha-badge {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#comment-recaptcha-disclaimer {
|
||||
text-align: justify;
|
||||
text-align-last: center;
|
||||
font-size: .7em;
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
}
|
||||
{%- endif -%}
|
||||
|
||||
{%- if site.google_forms_comments.google_app_script -%}
|
||||
#comment-submit-error {
|
||||
color: red;
|
||||
display: none;
|
||||
}
|
||||
{%- endif -%}
|
||||
|
||||
.comment-info-text {
|
||||
letter-spacing: 0.5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.comment-info-text p {
|
||||
margin: 0 0 1rem;
|
||||
text-align: justify;
|
||||
text-align-last: center;
|
||||
font-size: .9em;
|
||||
}
|
||||
|
||||
#comment-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#comment-section, #load-comments {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
{%- if lazy_load_enabled -%}
|
||||
#comments-and-input {
|
||||
display: none;
|
||||
}
|
||||
{%- else -%}
|
||||
#load-comments {
|
||||
display: none;
|
||||
}
|
||||
{%- endif -%}
|
||||
</style>
|
||||
{%- endif -%}
|
@ -1,211 +0,0 @@
|
||||
<link href="https://fonts.googleapis.com/css?family=Poppins:300,400,500,700,900&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
h1 {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
i {
|
||||
font-size: 2.2rem;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin-left: 3px;
|
||||
width: 99%;
|
||||
background-color: #dadce0;
|
||||
}
|
||||
|
||||
.content-form {
|
||||
padding: 5%;
|
||||
}
|
||||
|
||||
.card-grid {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
grid-gap: 2rem;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
}
|
||||
|
||||
.input-group {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #383B40;
|
||||
box-shadow: 2px 2px 12px 1px rgba(8, 8, 8, 0.5);
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
color: #00eeff;
|
||||
}
|
||||
|
||||
input[type=submit] {
|
||||
border: none;
|
||||
color: #FEFCFB;
|
||||
background-color: #034078;
|
||||
padding: 15px 15px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 16px;
|
||||
width: 100px;
|
||||
margin-right: 10px;
|
||||
margin-left: 10px;
|
||||
border-radius: 10px;
|
||||
transition-duration: 0.4s;
|
||||
}
|
||||
|
||||
input[type=submit]:hover {
|
||||
background-color: #1282A2;
|
||||
}
|
||||
|
||||
button {
|
||||
border: none;
|
||||
color: #FEFCFB;
|
||||
padding: 15px 32px;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
width: 100px;
|
||||
border-radius: 10px;
|
||||
transition-duration: 0.4s;
|
||||
}
|
||||
|
||||
.ideation label {
|
||||
font-size: 1.2rem;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.ideation large {
|
||||
width: 100%;
|
||||
padding-left: 10px;
|
||||
padding-top: 10px;
|
||||
padding-right: 10px;
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.ideation small {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
input[type=button] {
|
||||
padding: 1px 2px;
|
||||
margin-left: 10px;
|
||||
text-align: right;
|
||||
border-radius: 6px;
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
font-size: large;
|
||||
color: #1b0c8787;
|
||||
}
|
||||
|
||||
.form-button {
|
||||
border: 0;
|
||||
border-radius: 8px;
|
||||
background: #6f55d5;
|
||||
color: #fff;
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
font-weight: bold;
|
||||
font-size: 0.9em;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 20px;
|
||||
outline-style: none;
|
||||
padding: 10px 20px;
|
||||
/* box-shadow: 2px 2px 4px 1px rgba(8, 8, 8, 0.5); */
|
||||
box-shadow: rgba(50, 50, 93, 0.25) 0px 50px 100px -20px, rgba(0, 0, 0, 0.3) 0px 30px 60px -30px, rgba(10, 37, 64, 0.35) 0px -2px 6px 0px inset;
|
||||
width: auto;
|
||||
min-width: 25%;
|
||||
transition-duration: 0.4s;
|
||||
}
|
||||
|
||||
.form-button:hover {
|
||||
background-color: #6f55d5;
|
||||
background-image: linear-gradient(#6f55d5, #5739ce);
|
||||
}
|
||||
|
||||
.form-button:active {
|
||||
background-color: #5739ce;
|
||||
background-image: linear-gradient(#5739ce, #6f55d5);
|
||||
box-shadow: rgba(50, 50, 93, 0.25) 0px 30px 60px -12px inset, rgba(0, 0, 0, 0.3) 0px 18px 36px -18px inset;
|
||||
}
|
||||
|
||||
@import url("https://fonts.googleapis.com/css?family=Source+Sans+Pro");
|
||||
|
||||
.form-item {
|
||||
position: relative;
|
||||
padding: 0.5em 2.5em;
|
||||
background: white;
|
||||
color: black;
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
width: 95%;
|
||||
margin: 1em auto;
|
||||
box-shadow: 2px 2px 12px 1px rgba(8, 8, 8, 0.5);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.form-button:disabled::after,
|
||||
.form-button[disabled]::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
border: 4px solid transparent;
|
||||
border-top-color: #ffffff;
|
||||
border-radius: 50%;
|
||||
-webkit-animation: button-loading-spinner 1s ease infinite;
|
||||
animation: button-loading-spinner 1s ease infinite;
|
||||
}
|
||||
|
||||
@keyframes button-loading-spinner {
|
||||
from {
|
||||
transform: rotate(0turn);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(1turn);
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes button-loading-spinner {
|
||||
from {
|
||||
transform: rotate(0turn);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(1turn);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<div class="content-form">
|
||||
<div style="color: #47464b;" align="center" class="title">
|
||||
<h1>{{ include.title }}</h1>
|
||||
<hr>
|
||||
</div>
|
||||
<div class="card-grid">
|
||||
<div class="card">
|
||||
<p align="center">
|
||||
Coming Soon
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,22 +0,0 @@
|
||||
<!-- google iframe begin - place google form embed link here-->
|
||||
<style>
|
||||
.googleform {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
resize: width;
|
||||
overflow: auto; /* something other than visible */
|
||||
border-radius: 8px;
|
||||
}
|
||||
</style>
|
||||
<div class="googleform">
|
||||
<script type="text/javascript">var submitted = false;</script>
|
||||
<iframe name="hidden_iframe" id="hidden_iframe" style="display:none;"
|
||||
onload="if(submitted) {window.location='suggestions.html';}"></iframe>
|
||||
<form
|
||||
action="https://docs.google.com/forms/d/e/1FAIpQLScQG7vXRrBQU1N82K-hQWLFx-0UZ6exRcwgcaEa6ao86RLUdw/viewform?embedded=true"
|
||||
method="post" target="hidden_iframe" onsubmit="submitted=true;">
|
||||
{% include custom/misc/form.html %}
|
||||
|
||||
</form>
|
||||
</div>
|
||||
<!-- google iframe end -->
|
@ -1,38 +0,0 @@
|
||||
<!--
|
||||
This is a list of posts.
|
||||
Note that the post variable only exists inside the for loop above.
|
||||
If you wish to access the currently-rendering page/posts’s variables
|
||||
(the variables of the post/page that has the for loop in it), use the page variable instead.
|
||||
|
||||
Here is the official documentation:
|
||||
|
||||
http://jekyllrb.com/docs/posts/
|
||||
|
||||
-->
|
||||
<ul>
|
||||
{% for post in site.posts %}
|
||||
<li>
|
||||
<a href="{{ post.url }}">{{ post.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<!-- <ul>
|
||||
Here's an example of outputting a list of blog posts with an excerpt:
|
||||
|
||||
{% for post in site.posts %}
|
||||
<li>
|
||||
<a href="{{ post.url }}">{{ post.title }}</a>
|
||||
{{ post.excerpt }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul> -->
|
||||
|
||||
<!-- {% for tag in site.tags %}
|
||||
<h3>{{ tag[0] }}</h3>
|
||||
<ul>
|
||||
{% for post in tag[1] %}
|
||||
<li><a href="{{ post.url }}">{{ post.title }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endfor %} -->
|
@ -1,70 +0,0 @@
|
||||
<!-- <figure class="image">
|
||||
<img src="{{ include.url }}" alt="{{ include.description }}">
|
||||
<figcaption>{{ include.description }}</figcaption>
|
||||
</figure> -->
|
||||
<style>
|
||||
.image-{{ include.image }} {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/* align-items: center; */
|
||||
justify-content: space-between;
|
||||
/* justify-content: center; */
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.image-{{ include.image }} img {
|
||||
flex-shrink: 0;
|
||||
width: {{ include.width }}px;
|
||||
height: {{ include.height }}px;
|
||||
object-fit: cover;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.image-{{ include.image }} figcaption {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.image-card-grid-{{ include.image }} {
|
||||
max-width: {{ include.width }}px;
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
grid-gap: 2rem;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
}
|
||||
|
||||
.image-card-{{ include.image }} {
|
||||
flex-shrink: 0;
|
||||
width: {{ include.width }}px;
|
||||
height: {{ include.height }}px;
|
||||
object-fit: cover;
|
||||
background-color: white;
|
||||
box-shadow: 2px 2px 12px 1px rgba(8, 8, 8, 0.5);
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.image-content-form-{{ include.image }} {
|
||||
padding: 5%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
/* justify-content: center; */
|
||||
overflow: hidden;
|
||||
}
|
||||
.p-image-{{ include.image }}{
|
||||
align-self: center;
|
||||
}
|
||||
</style>
|
||||
<p class="p-image-{{ include.image }}" align="center">
|
||||
<div class="image-content-form-{{ include.image }}">
|
||||
<div class="image-card-grid-{{ include.image }}">
|
||||
<div class="image-card-{{ include.image }}">
|
||||
<figure class="image-{{ include.image }}">
|
||||
<img draggable="false" class="image-{{ include.image }}" src="{{ include.src }}" alt="{{ include.tags }}">
|
||||
<div style="padding-top: 10px"></div>
|
||||
<figcaption><i>{{ include.description }}</i></figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</p>
|
@ -1,186 +0,0 @@
|
||||
<!-- Trigger/Open The Modal -->
|
||||
<style>
|
||||
/* Style the Image Used to Trigger the Modal */
|
||||
#myImg {
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
#myImg:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* The Modal (background) */
|
||||
.modal {
|
||||
display: none;
|
||||
/* Hidden by default */
|
||||
position: fixed;
|
||||
/* Stay in place */
|
||||
z-index: 2;
|
||||
/* Sit on top */
|
||||
padding-top: 100px;
|
||||
/* Location of the box */
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
/* Full width */
|
||||
height: 100%;
|
||||
/* Full height */
|
||||
overflow: auto;
|
||||
/* Enable scroll if needed */
|
||||
background-color: rgb(0, 0, 0);
|
||||
/* Fallback color */
|
||||
background-color: rgba(0, 0, 0, 0.9);
|
||||
/* Black w/ opacity */
|
||||
}
|
||||
|
||||
/* Modal Content (Image) */
|
||||
.modal-content {
|
||||
margin: auto;
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 700px;
|
||||
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2),
|
||||
0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||
animation: fadeIn 0.8s;
|
||||
-webkit-animation: fadeIn 0.8s;
|
||||
-moz-animation: fadeIn 0.8s;
|
||||
-o-animation: fadeIn 0.8s;
|
||||
-ms-animation: fadeIn 0.8s;
|
||||
}
|
||||
|
||||
/* Caption of Modal Image (Image Text) - Same Width as the Image */
|
||||
#caption {
|
||||
margin: auto;
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 700px;
|
||||
text-align: center;
|
||||
color: #ccc;
|
||||
padding: 10px 0;
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
/* Add Animation - Zoom in the Modal */
|
||||
.modal-content,
|
||||
#caption {
|
||||
animation-name: zoom;
|
||||
animation-duration: 0.6s;
|
||||
}
|
||||
|
||||
@keyframes zoom {
|
||||
from {
|
||||
transform: scale(0)
|
||||
}
|
||||
|
||||
to {
|
||||
transform: scale(1)
|
||||
}
|
||||
}
|
||||
|
||||
/* The Close Button */
|
||||
.close {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 35px;
|
||||
color: #f1f1f1;
|
||||
font-size: 40px;
|
||||
font-weight: bold;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.close:hover,
|
||||
.close:focus {
|
||||
color: #bbb;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 100% Image Width on Smaller Screens */
|
||||
@media only screen and (max-width: 700px) {
|
||||
.modal-content {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.modal::-webkit-scrollbar {
|
||||
display: none;
|
||||
/* Safari and Chrome */
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@-moz-keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@-o-keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@-ms-keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<!-- The Modal -->
|
||||
<div>
|
||||
<div id="myModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<span class="close" onclick="toggleCloseModal()">×</span>
|
||||
{% if include.header %}
|
||||
<h2>Modal Header</h2>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% include modal/image.html height=include.height width=include.width title=include.title
|
||||
image=include.category description=include.description src=include.src %}
|
||||
{% if include.footer ==true %}
|
||||
<div class="modal-footer">
|
||||
<h3>Modal Footer</h3>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<a href="#" onclick="toggleModal()" title="Toggle Modal" id="myImg">
|
||||
{% include modal/image.html height=include.height width=include.width title=include.title
|
||||
image=include.category description=include.description src=include.src %}
|
||||
</a>
|
||||
</div>
|
@ -1,65 +0,0 @@
|
||||
{%- comment -%}
|
||||
This file can be used to fix the HTML produced by Jekyll for highlighted
|
||||
code with line numbers.
|
||||
|
||||
It works with `{% highlight some_language linenos %}...{% endhighlight %}`
|
||||
and with the Kramdown option to add line numbers to fenced code.
|
||||
|
||||
The implementation was derived from the workaround provided by
|
||||
Dmitry Hrabrov (DeXP) at
|
||||
https://github.com/penibelst/jekyll-compress-html/issues/71#issuecomment-188144901
|
||||
|
||||
EXPLANATION
|
||||
|
||||
The HTML produced by Rouge highlighting with lie numbers is of the form
|
||||
`code table`. Jekyll (<= 4.1.1) always wraps the highlighted HTML
|
||||
with `pre`. This wrapping is not only unnecessary, but also transforms
|
||||
the conforming HTML produced by Rouge to non-conforming HTML, which
|
||||
results in HTML validation error reports.
|
||||
|
||||
The fix removes the outer `pre` tags whenever they contain the pattern
|
||||
`<table class="rouge-table">`.
|
||||
|
||||
Apart from avoiding HTML validation errors, the fix allows the use of
|
||||
the [Jekyll layout for compressing HTML](http://jch.penibelst.de),
|
||||
which relies on `pre` tags not being nested, according to
|
||||
https://github.com/penibelst/jekyll-compress-html/issues/71#issuecomment-172069842
|
||||
|
||||
USAGE
|
||||
|
||||
(Any names can be used for `some_var` and `some_language`.)
|
||||
|
||||
{% capture some_var %}
|
||||
{% highlight some_language linenos %}
|
||||
Some code
|
||||
{% endhighlight %}
|
||||
{% endcapture %}
|
||||
{% include fix_linenos.html code=some_var %}
|
||||
|
||||
For code fences:
|
||||
|
||||
{% capture some_var %}
|
||||
```some_language
|
||||
Some code
|
||||
```
|
||||
{% endcapture %}
|
||||
{% assign some_var = some_var | markdownify %}
|
||||
{% include fix_linenos.html code=some_var %}
|
||||
|
||||
CAVEATS
|
||||
|
||||
The above does not work when `Some code` happens to contain the matched string
|
||||
`<table class="rouge-table">`.
|
||||
|
||||
The use of this file overwrites the variable `fix_linenos_code` with `nil`.
|
||||
|
||||
{%- endcomment -%}
|
||||
|
||||
{% assign fix_linenos_code = include.code %}
|
||||
{% if fix_linenos_code contains '<table class="rouge-table">' %}
|
||||
{% assign fix_linenos_code = fix_linenos_code | replace: '<pre class="highlight">', '<pre>' %}
|
||||
{% assign fix_linenos_code = fix_linenos_code | replace: "<pre><code", "<code" %}
|
||||
{% assign fix_linenos_code = fix_linenos_code | replace: "</code></pre>", "</code>" %}
|
||||
{% endif %}
|
||||
{{ fix_linenos_code }}
|
||||
{% assign fix_linenos_code = nil %}
|
@ -1,32 +0,0 @@
|
||||
<!-- Generate footer -->
|
||||
<style>
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: blue;
|
||||
}
|
||||
|
||||
img {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.footer-logo {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin-top: -10px;
|
||||
margin-bottom: 10px;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="footer-logo">
|
||||
<img width="30px" height="20px" title="EyeTrackVRLogo"
|
||||
src="{{ 'assets/images/favicon/logo_no_bg.svg' | relative_url }}" alt="EyeTrackVRLogo">
|
||||
Copyright © 2019-current EyeTrackVR. Distributed by an <a
|
||||
href="https://github.com/RedHawk989/EyeTrackVR/blob/main/LICENSE">MIT</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,23 +0,0 @@
|
||||
/*This function will load script and call the callback once the script has loaded*/
|
||||
function loadScriptAsync(scriptSrc, callback) {
|
||||
if (typeof callback !== "function") {
|
||||
throw new Error("Not a valid callback for async script load");
|
||||
}
|
||||
var script = document.createElement("script");
|
||||
script.onload = callback;
|
||||
script.src = scriptSrc;
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
|
||||
/* This is the part where you call the above defined function and "call back" your code which gets executed after the script has loaded */
|
||||
loadScriptAsync(
|
||||
"https://www.googletagmanager.com/gtag/js?id={#YOUR-TRACKING-ID}",
|
||||
function () {
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag() {
|
||||
dataLayer.push(arguments);
|
||||
}
|
||||
gtag("js", new Date());
|
||||
gtag("config", "{#YOUR-TRACKING-ID}", { anonymize_ip: true });
|
||||
}
|
||||
);
|
@ -1,60 +0,0 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
|
||||
<meta http-equiv="Access-Control-Allow-Origin" content="*" />
|
||||
|
||||
{% unless site.plugins contains "jekyll-seo-tag" %}
|
||||
<title>{{ page.title }} - {{ site.title }}</title>
|
||||
|
||||
{% if page.description %}
|
||||
<meta name="Description" content="{{ page.description }}">
|
||||
{% endif %}
|
||||
{% endunless %}
|
||||
|
||||
<link rel="shortcut icon" href="{{ '/assets/images/favicon.ico' | relative_url }}" type="image/x-icon">
|
||||
|
||||
{% if false %}
|
||||
<link rel="stylesheet" href="{{ '/assets/css/just-the-docs-default.css' | relative_url }}">
|
||||
{% endif %}
|
||||
|
||||
<script>
|
||||
/* If `prefers-color-scheme` is not supported, fall back to default mode */
|
||||
|
||||
if (window.matchMedia('(prefers-color-scheme: dark)').media === 'not all') {
|
||||
/* document.documentElement.style.display = 'none'; */
|
||||
document.head.insertAdjacentHTML(
|
||||
'beforeend',
|
||||
'<link rel="stylesheet" href="{{ \'/assets/css/just-the-docs-default.css\' | relative_url }}" onload="document.documentElement.style.display = \'\'">',
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Browser Detection of preferred color scheme -->
|
||||
<link rel="stylesheet" href="{{ '/assets/css/just-the-docs-eyetrackvr.css' | relative_url }}"
|
||||
media="(prefers-color-scheme: dark)" />
|
||||
<link rel="stylesheet" href="{{ '/assets/css/just-the-docs-light.css' | relative_url }}"
|
||||
media="(prefers-color-scheme: light)" />
|
||||
|
||||
{% if site.ga_tracking != nil %}
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id={{ site.ga_tracking }}"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag() { dataLayer.push(arguments); }
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', '{{ site.ga_tracking }}'{% unless site.ga_tracking_anonymize_ip == nil %}, { 'anonymize_ip': true }{% endunless %});
|
||||
</script>
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if site.search_enabled != false %}
|
||||
<script type="text/javascript" src="{{ '/assets/js/vendor/lunr.min.js' | relative_url }}"></script>
|
||||
{% endif %}
|
||||
<script type="text/javascript" src="{{ '/assets/js/just-the-docs.js' | relative_url }}"></script>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
{% seo %}
|
||||
|
||||
{% include head_custom.html %}
|
||||
</head>
|
@ -1,17 +0,0 @@
|
||||
<link href="https://fonts.googleapis.com/css?family=Fira+Sans" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css?family=Fira+Mono" rel="stylesheet">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
|
||||
<script src="https://code.iconify.design/2/2.2.1/iconify.min.js"></script>
|
||||
<script type="module" src="https://unpkg.com/esp-web-tools@8.0.6/dist/web/install-button.js?module"></script>
|
||||
|
||||
<!-- Below is Favicon Stuffs -->
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="{{'assets/images/favicon/apple-touch-icon.png' | relative_url }}">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="{{'assets/images/favicon/favicon-32x32.png' | relative_url }}">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="{{'assets/images/favicon/favicon-16x16.png' | relative_url }}">
|
||||
<link rel="manifest" href="{{'assets/images/favicon/site.webmanifest' | relative_url }}">
|
||||
<link rel="mask-icon" href="{{'assets/images/favicon/safari-pinned-tab.svg' | relative_url }}" color="#5bbad5">
|
||||
<link rel="shortcut icon" href="{{'assets/images/favicon/favicon.ico' | relative_url }}">
|
||||
<meta name="msapplication-TileColor" content="#00a300">
|
||||
<meta name="msapplication-config" content="{{'assets/images/favicon/browserconfig.xml' | relative_url }}">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
<!-- End of Favicon Stuffs -->
|
@ -1,20 +0,0 @@
|
||||
<ul>
|
||||
<a href="javascript:toggleDetect()" title="Switching Schemes" class="btn btn-mode fs-2 mb-1 mb-md-0 mr-0"
|
||||
id="switch-mode">Dark Mode</a>
|
||||
</ul>
|
||||
<script type="text/javascript">
|
||||
const switch_scheme = document.getElementById("switch-mode");
|
||||
var isClicked = false;
|
||||
async function toggleDetect() {
|
||||
if (isClicked == false) {
|
||||
isClicked = true;
|
||||
switch_scheme.textContent = "Dark Mode";
|
||||
localStorage.setItem("theme", "light");
|
||||
} else {
|
||||
isClicked = false;
|
||||
switch_scheme.textContent = "Light Mode";
|
||||
localStorage.setItem("theme", "dark");
|
||||
}
|
||||
await switchScheme();
|
||||
}
|
||||
</script>
|
@ -1,6 +0,0 @@
|
||||
async function switchScheme() {
|
||||
localStorage.getItem('theme') === 'dark' ? jtd.setTheme("eyetrackvr") : jtd.setTheme("light");
|
||||
}
|
||||
window.onload = function () {
|
||||
switchScheme();
|
||||
};
|
@ -1,99 +0,0 @@
|
||||
<ul class="nav-list">
|
||||
{%- assign titled_pages = include.pages
|
||||
| where_exp:"item", "item.title != nil" -%}
|
||||
|
||||
{%- comment -%}
|
||||
The values of `title` and `nav_order` can be numbers or strings.
|
||||
Jekyll gives build failures when sorting on mixtures of different types,
|
||||
so numbers and strings need to be sorted separately.
|
||||
|
||||
Here, numbers are sorted by their values, and come before all strings.
|
||||
An omitted `nav_order` value is equivalent to the page's `title` value
|
||||
(except that a numerical `title` value is treated as a string).
|
||||
|
||||
The case-sensitivity of string sorting is determined by `site.nav_sort`.
|
||||
{%- endcomment -%}
|
||||
|
||||
{%- assign string_ordered_pages = titled_pages
|
||||
| where_exp:"item", "item.nav_order == nil" -%}
|
||||
{%- assign nav_ordered_pages = titled_pages
|
||||
| where_exp:"item", "item.nav_order != nil" -%}
|
||||
|
||||
{%- comment -%}
|
||||
The nav_ordered_pages have to be added to number_ordered_pages and
|
||||
string_ordered_pages, depending on the nav_order value.
|
||||
The first character of the jsonify result is `"` only for strings.
|
||||
{%- endcomment -%}
|
||||
{%- assign nav_ordered_groups = nav_ordered_pages
|
||||
| group_by_exp:"item", "item.nav_order | jsonify | slice: 0" -%}
|
||||
{%- assign number_ordered_pages = "" | split:"X" -%}
|
||||
{%- for group in nav_ordered_groups -%}
|
||||
{%- if group.name == '"' -%}
|
||||
{%- assign string_ordered_pages = string_ordered_pages | concat: group.items -%}
|
||||
{%- else -%}
|
||||
{%- assign number_ordered_pages = number_ordered_pages | concat: group.items -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
|
||||
{%- assign sorted_number_ordered_pages = number_ordered_pages | sort:"nav_order" -%}
|
||||
|
||||
{%- comment -%}
|
||||
The string_ordered_pages have to be sorted by nav_order, and otherwise title
|
||||
(where appending the empty string to a numeric title converts it to a string).
|
||||
After grouping them by those values, the groups are sorted, then the items
|
||||
of each group are concatenated.
|
||||
{%- endcomment -%}
|
||||
{%- assign string_ordered_groups = string_ordered_pages
|
||||
| group_by_exp:"item", "item.nav_order | default: item.title | append:''" -%}
|
||||
{%- if site.nav_sort == 'case_insensitive' -%}
|
||||
{%- assign sorted_string_ordered_groups = string_ordered_groups | sort_natural:"name" -%}
|
||||
{%- else -%}
|
||||
{%- assign sorted_string_ordered_groups = string_ordered_groups | sort:"name" -%}
|
||||
{%- endif -%}
|
||||
{%- assign sorted_string_ordered_pages = "" | split:"X" -%}
|
||||
{%- for group in sorted_string_ordered_groups -%}
|
||||
{%- assign sorted_string_ordered_pages = sorted_string_ordered_pages | concat: group.items -%}
|
||||
{%- endfor -%}
|
||||
|
||||
{%- assign pages_list = sorted_number_ordered_pages | concat: sorted_string_ordered_pages -%}
|
||||
|
||||
{%- for node in pages_list -%}
|
||||
{%- if node.parent == nil -%}
|
||||
{%- unless node.nav_exclude -%}
|
||||
<li class="nav-list-item{% if page.url == node.url or page.parent == node.title or page.grand_parent == node.title %} active{% endif %}">
|
||||
{%- if node.has_children -%}
|
||||
<a href="#" class="nav-list-expander"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a>
|
||||
{%- endif -%}
|
||||
<a href="{{ node.url | absolute_url }}" class="nav-list-link{% if page.url == node.url %} active{% endif %}">{{ node.title }}</a>
|
||||
{%- if node.has_children -%}
|
||||
{%- assign children_list = pages_list | where: "parent", node.title -%}
|
||||
<ul class="nav-list ">
|
||||
{%- for child in children_list -%}
|
||||
{%- unless child.nav_exclude -%}
|
||||
<li class="nav-list-item {% if page.url == child.url or page.parent == child.title %} active{% endif %}">
|
||||
{%- if child.has_children -%}
|
||||
<a href="#" class="nav-list-expander"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a>
|
||||
{%- endif -%}
|
||||
<a href="{{ child.url | absolute_url }}" class="nav-list-link{% if page.url == child.url %} active{% endif %}">{{ child.title }}</a>
|
||||
{%- if child.has_children -%}
|
||||
{%- assign grand_children_list = pages_list | where: "parent", child.title | where: "grand_parent", node.title -%}
|
||||
<ul class="nav-list">
|
||||
{%- for grand_child in grand_children_list -%}
|
||||
{%- unless grand_child.nav_exclude -%}
|
||||
<li class="nav-list-item {% if page.url == grand_child.url %} active{% endif %}">
|
||||
<a href="{{ grand_child.url | absolute_url }}" class="nav-list-link{% if page.url == grand_child.url %} active{% endif %}">{{ grand_child.title }}</a>
|
||||
</li>
|
||||
{%- endunless -%}
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{%- endunless -%}
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{%- endunless -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
</ul>
|
@ -1,5 +0,0 @@
|
||||
<!-- Do not edit this file - it is a template. Please edit the _data/people/contributors/individuals.yml file -->
|
||||
|
||||
{% for member in site.data.people.contributors.individuals %}
|
||||
{% if member.name != null and member.name != "" %} - {{ member.name }} {% endif %}{% if member.github != null and member.github != "" %} [](https://github.com/{{ member.github }}){:target="_blank"} {% endif %} {% if member.linkedin != null and member.linkedin != "" %} [](https://www.linkedin.com/in/{{ member.linkedin }}/){:target="_blank"} {% endif %} {% if member.twitter != null and member.twitter != "" %} [](https://twitter.com/{{member.twitter}}){:target="_blank"}{% endif %} {% if member.description != null and member.description != "" %} - {{ member.description }} {% endif %}
|
||||
{% endfor %}
|
@ -1,8 +0,0 @@
|
||||
<!-- Do not edit this file - it is a template. Please edit the _data/people/key_members/key_members.yml file -->
|
||||
|
||||
{% for member in site.data.people.credits.credits %}
|
||||
{% if member.name != null and member.name != "" %} - {% endif %}{% if member.url != null and
|
||||
member.url != "" %} [{{ member.name }}]({{ member.url }}){:target="_blank"} {% endif %} {% if member.description != null and
|
||||
member.description != "" %} - {{
|
||||
member.description }} {% endif %}
|
||||
{% endfor %}
|
@ -1,5 +0,0 @@
|
||||
<!-- Do not edit this file - it is a template. Please edit the _data/people/key_members/key_members.yml file -->
|
||||
|
||||
{% for member in site.data.people.keymembers.key_members %}
|
||||
{% if member.name != null and member.name != "" %} - {{ member.name }} {% endif %}{% if member.github != null and member.github != "" %} [](https://github.com/{{ member.github }}){:target="_blank"} {% endif %} {% if member.linkedin != null and member.linkedin != "" %} [](https://www.linkedin.com/in/{{ member.linkedin }}/){:target="_blank"} {% endif %} {% if member.twitter != null and member.twitter != "" %} [](https://twitter.com/{{member.twitter}}){:target="_blank"}{% endif %} {% if member.description != null and member.description != "" %} - {{ member.description }} {% endif %}
|
||||
{% endfor %}
|
@ -1,15 +0,0 @@
|
||||
---
|
||||
layout: default
|
||||
title: Authors
|
||||
---
|
||||
<h1>Staff</h1>
|
||||
|
||||
<ul>
|
||||
{% for author in site.authors %}
|
||||
<li>
|
||||
<h2><a href="{{ author.url }}">{{ author.name }}</a></h2>
|
||||
<h3>{{ author.position }}</h3>
|
||||
<p>{{ author.content | markdownify }}</p>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
@ -1,14 +0,0 @@
|
||||
<div class="recent-articles">
|
||||
<h2>Recently Published</h2>
|
||||
{% assign maxposts = 5 %}
|
||||
<ul class="post-list text-muted list-unstyled">
|
||||
{% for post in site.posts limit: maxposts %}
|
||||
<li>
|
||||
<p>
|
||||
<a class="article-link" href="">
|
||||
{{ post.title | escape }}</a>
|
||||
</p>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
@ -1,5 +0,0 @@
|
||||
{% if site.logo %}
|
||||
<div class="site-logo"></div>
|
||||
{% else %}
|
||||
{{ site.title }}
|
||||
{% endif %}
|
144
docs/_includes/vendor/anchor_headings.html
vendored
144
docs/_includes/vendor/anchor_headings.html
vendored
@ -1,144 +0,0 @@
|
||||
{% capture headingsWorkspace %}
|
||||
{% comment %}
|
||||
Copyright (c) 2018 Vladimir "allejo" Jimenez
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
{% endcomment %}
|
||||
{% comment %}
|
||||
Version 1.0.7
|
||||
https://github.com/allejo/jekyll-anchor-headings
|
||||
|
||||
"Be the pull request you wish to see in the world." ~Ben Balter
|
||||
|
||||
Usage:
|
||||
{% include anchor_headings.html html=content anchorBody="#" %}
|
||||
|
||||
Parameters:
|
||||
* html (string) - the HTML of compiled markdown generated by kramdown in Jekyll
|
||||
|
||||
Optional Parameters:
|
||||
* beforeHeading (bool) : false - Set to true if the anchor should be placed _before_ the heading's content
|
||||
* anchorAttrs (string) : '' - Any custom HTML attributes that will be added to the `<a>` tag; you may NOT use `href`, `class` or `title`;
|
||||
the `%heading%` and `%html_id%` placeholders are available
|
||||
* anchorBody (string) : '' - The content that will be placed inside the anchor; the `%heading%` placeholder is available
|
||||
* anchorClass (string) : '' - The class(es) that will be used for each anchor. Separate multiple classes with a space
|
||||
* anchorTitle (string) : '' - The `title` attribute that will be used for anchors
|
||||
* h_min (int) : 1 - The minimum header level to build an anchor for; any header lower than this value will be ignored
|
||||
* h_max (int) : 6 - The maximum header level to build an anchor for; any header greater than this value will be ignored
|
||||
* bodyPrefix (string) : '' - Anything that should be inserted inside of the heading tag _before_ its anchor and content
|
||||
* bodySuffix (string) : '' - Anything that should be inserted inside of the heading tag _after_ its anchor and content
|
||||
|
||||
Output:
|
||||
The original HTML with the addition of anchors inside of all of the h1-h6 headings.
|
||||
{% endcomment %}
|
||||
|
||||
{% assign minHeader = include.h_min | default: 1 %}
|
||||
{% assign maxHeader = include.h_max | default: 6 %}
|
||||
{% assign beforeHeading = include.beforeHeading %}
|
||||
{% assign nodes = include.html | split: '<h' %}
|
||||
|
||||
{% capture edited_headings %}{% endcapture %}
|
||||
|
||||
{% for _node in nodes %}
|
||||
{% capture node %}{{ _node | strip }}{% endcapture %}
|
||||
|
||||
{% if node == "" %}
|
||||
{% continue %}
|
||||
{% endif %}
|
||||
|
||||
{% assign nextChar = node | replace: '"', '' | strip | slice: 0, 1 %}
|
||||
{% assign headerLevel = nextChar | times: 1 %}
|
||||
|
||||
<!-- If the level is cast to 0, it means it's not a h1-h6 tag, so let's see if we need to fix it -->
|
||||
{% if headerLevel == 0 %}
|
||||
<!-- Split up the node based on closing angle brackets and get the first one. -->
|
||||
{% assign firstChunk = node | split: '>' | first %}
|
||||
|
||||
<!-- If the first chunk does NOT contain a '<', that means we've broken another HTML tag that starts with 'h' -->
|
||||
{% unless firstChunk contains '<' %}
|
||||
{% capture node %}<h{{ node }}{% endcapture %}
|
||||
{% endunless %}
|
||||
|
||||
{% capture edited_headings %}{{ edited_headings }}{{ node }}{% endcapture %}
|
||||
{% continue %}
|
||||
{% endif %}
|
||||
|
||||
{% capture _closingTag %}</h{{ headerLevel }}>{% endcapture %}
|
||||
{% assign _workspace = node | split: _closingTag %}
|
||||
{% assign _idWorkspace = _workspace[0] | split: 'id="' %}
|
||||
{% assign _idWorkspace = _idWorkspace[1] | split: '"' %}
|
||||
{% assign html_id = _idWorkspace[0] %}
|
||||
|
||||
{% capture _hAttrToStrip %}{{ _workspace[0] | split: '>' | first }}>{% endcapture %}
|
||||
{% assign header = _workspace[0] | replace: _hAttrToStrip, '' %}
|
||||
|
||||
<!-- Build the anchor to inject for our heading -->
|
||||
{% capture anchor %}{% endcapture %}
|
||||
|
||||
{% if html_id and headerLevel >= minHeader and headerLevel <= maxHeader %}
|
||||
{% capture anchor %}href="#{{ html_id }}"{% endcapture %}
|
||||
|
||||
{% if include.anchorClass %}
|
||||
{% capture anchor %}{{ anchor }} class="{{ include.anchorClass }}"{% endcapture %}
|
||||
{% endif %}
|
||||
|
||||
{% if include.anchorTitle %}
|
||||
{% capture anchor %}{{ anchor }} title="{{ include.anchorTitle | replace: '%heading%', header }}"{% endcapture %}
|
||||
{% endif %}
|
||||
|
||||
{% if include.anchorAttrs %}
|
||||
{% capture anchor %}{{ anchor }} {{ include.anchorAttrs | replace: '%heading%', header | replace: '%html_id%', html_id }}{% endcapture %}
|
||||
{% endif %}
|
||||
|
||||
{% capture anchor %}<a {{ anchor }}>{{ include.anchorBody | replace: '%heading%', header | default: '' }}</a>{% endcapture %}
|
||||
|
||||
<!-- In order to prevent adding extra space after a heading, we'll let the 'anchor' value contain it -->
|
||||
{% if beforeHeading %}
|
||||
{% capture anchor %}{{ anchor }} {% endcapture %}
|
||||
{% else %}
|
||||
{% capture anchor %} {{ anchor }}{% endcapture %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% capture new_heading %}
|
||||
<h{{ _hAttrToStrip }}
|
||||
{{ include.bodyPrefix }}
|
||||
{% if beforeHeading %}
|
||||
{{ anchor }}{{ header }}
|
||||
{% else %}
|
||||
{{ header }}{{ anchor }}
|
||||
{% endif %}
|
||||
{{ include.bodySuffix }}
|
||||
</h{{ headerLevel }}>
|
||||
{% endcapture %}
|
||||
|
||||
<!--
|
||||
If we have content after the `</hX>` tag, then we'll want to append that here so we don't lost any content.
|
||||
-->
|
||||
{% assign chunkCount = _workspace | size %}
|
||||
{% if chunkCount > 1 %}
|
||||
{% capture new_heading %}{{ new_heading }}{{ _workspace | last }}{% endcapture %}
|
||||
{% endif %}
|
||||
|
||||
{% capture edited_headings %}{{ edited_headings }}{{ new_heading }}{% endcapture %}
|
||||
{% endfor %}
|
||||
{% endcapture %}{% assign headingsWorkspace = '' %}{{ edited_headings | strip }}
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
layout: default
|
||||
---
|
||||
|
||||
{{ content }}
|
@ -1,7 +0,0 @@
|
||||
---
|
||||
layout: default
|
||||
---
|
||||
<h1>{{ page.name }}</h1>
|
||||
<h2>{{ page.position }}</h2>
|
||||
|
||||
{{ content }}
|
@ -1,235 +0,0 @@
|
||||
---
|
||||
layout: table_wrappers
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="{{ site.lang | default: 'en-US' }}">
|
||||
{% include head.html %}
|
||||
|
||||
<body>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
|
||||
<symbol id="svg-link" viewBox="0 0 24 24">
|
||||
<title>Link</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||
class="feather feather-link">
|
||||
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path>
|
||||
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
|
||||
</svg>
|
||||
</symbol>
|
||||
<symbol id="svg-search" viewBox="0 0 24 24">
|
||||
<title>Search</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||
class="feather feather-search">
|
||||
<circle cx="11" cy="11" r="8"></circle>
|
||||
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
||||
</svg>
|
||||
</symbol>
|
||||
<symbol id="svg-menu" viewBox="0 0 24 24">
|
||||
<title>Menu</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||
class="feather feather-menu">
|
||||
<line x1="3" y1="12" x2="21" y2="12"></line>
|
||||
<line x1="3" y1="6" x2="21" y2="6"></line>
|
||||
<line x1="3" y1="18" x2="21" y2="18"></line>
|
||||
</svg>
|
||||
</symbol>
|
||||
<symbol id="svg-arrow-right" viewBox="0 0 24 24">
|
||||
<title>Expand</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||
class="feather feather-chevron-right">
|
||||
<polyline points="9 18 15 12 9 6"></polyline>
|
||||
</svg>
|
||||
</symbol>
|
||||
<symbol id="svg-doc" viewBox="0 0 24 24">
|
||||
<title>Document</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||
class="feather feather-file">
|
||||
<path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path>
|
||||
<polyline points="13 2 13 9 20 9"></polyline>
|
||||
</svg>
|
||||
</symbol>
|
||||
</svg>
|
||||
|
||||
<div class="side-bar">
|
||||
<div class="site-header">
|
||||
<a href="{{ '/' | absolute_url }}" class="site-title lh-tight">{% include title.html %}</a>
|
||||
<a href="#" id="menu-button" class="site-button">
|
||||
<svg viewBox="0 0 24 24" class="icon">
|
||||
<use xlink:href="#svg-menu"></use>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
<nav role="navigation" aria-label="Main" id="site-nav" class="site-nav">
|
||||
{% if site.just_the_docs.collections %}
|
||||
{% assign collections_size = site.just_the_docs.collections | size %}
|
||||
{% for collection_entry in site.just_the_docs.collections %}
|
||||
{% assign collection_key = collection_entry[0] %}
|
||||
{% assign collection_value = collection_entry[1] %}
|
||||
{% assign collection = site[collection_key] %}
|
||||
{% if collection_value.nav_exclude != true %}
|
||||
{% if collections_size > 1 %}
|
||||
<div class="nav-category">{{ collection_value.name }}</div>
|
||||
{% endif %}
|
||||
{% include nav.html pages=collection %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% include nav.html pages=site.html_pages %}
|
||||
{% endif %}
|
||||
</nav>
|
||||
<footer class="site-footer">
|
||||
</footer>
|
||||
</div>
|
||||
<div class="main" id="top">
|
||||
<div id="main-header" class="main-header">
|
||||
{% if site.search_enabled != false %}
|
||||
<div class="search">
|
||||
<div class="search-input-wrap">
|
||||
<input type="text" id="search-input" class="search-input" tabindex="0"
|
||||
placeholder="Search {{ site.title }}" aria-label="Search {{ site.title }}" autocomplete="off">
|
||||
<label for="search-input" class="search-label"><svg viewBox="0 0 24 24" class="search-icon">
|
||||
<use xlink:href="#svg-search"></use>
|
||||
</svg></label>
|
||||
</div>
|
||||
<div id="search-results" class="search-results"></div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% include header_custom.html %}
|
||||
{% if site.aux_links %}
|
||||
<nav aria-label="Auxiliary" class="aux-nav">
|
||||
<ul class="aux-nav-list">
|
||||
{% for link in site.aux_links %}
|
||||
<li class="aux-nav-list-item">
|
||||
<a href="{{ link.last }}" class="site-button" {% if site.aux_links_new_tab %} target="_blank"
|
||||
rel="noopener noreferrer" {% endif %}>
|
||||
{{ link.first }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div id="main-content-wrap" class="main-content-wrap">
|
||||
{% unless page.url == "/" %}
|
||||
{% if page.parent %}
|
||||
{%- for node in pages_list -%}
|
||||
{%- if node.parent == nil -%}
|
||||
{%- if page.parent == node.title or page.grand_parent == node.title -%}
|
||||
{%- assign first_level_url = node.url | absolute_url -%}
|
||||
{%- endif -%}
|
||||
{%- if node.has_children -%}
|
||||
{%- assign children_list = pages_list | where: "parent", node.title -%}
|
||||
{%- for child in children_list -%}
|
||||
{%- if page.url == child.url or page.parent == child.title -%}
|
||||
{%- assign second_level_url = child.url | absolute_url -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
<nav aria-label="Breadcrumb" class="breadcrumb-nav">
|
||||
<ol class="breadcrumb-nav-list">
|
||||
{% if page.grand_parent %}
|
||||
<li class="breadcrumb-nav-list-item"><a href="{{ first_level_url }}">{{ page.grand_parent }}</a>
|
||||
</li>
|
||||
<li class="breadcrumb-nav-list-item"><a href="{{ second_level_url }}">{{ page.parent }}</a></li>
|
||||
{% else %}
|
||||
<li class="breadcrumb-nav-list-item"><a href="{{ first_level_url }}">{{ page.parent }}</a></li>
|
||||
{% endif %}
|
||||
<li class="breadcrumb-nav-list-item"><span>{{ page.title }}</span></li>
|
||||
</ol>
|
||||
</nav>
|
||||
{% endif %}
|
||||
{% endunless %}
|
||||
<div id="main-content" class="main-content" role="main">
|
||||
{% if site.heading_anchors != false %}
|
||||
{% include vendor/anchor_headings.html html=content beforeHeading="true" anchorBody="<svg viewBox=\"0 0
|
||||
16 16\" aria-hidden=\"true\">
|
||||
<use xlink:href=\"#svg-link\"></use>
|
||||
</svg>" anchorClass="anchor-heading" anchorAttrs="aria-labelledby=\"%html_id%\"" %}
|
||||
{% else %}
|
||||
{{ content }}
|
||||
{% endif %}
|
||||
|
||||
{% if page.has_children == true and page.has_toc != false %}
|
||||
<hr>
|
||||
<h2 class="text-delta">Table of contents</h2>
|
||||
<ul>
|
||||
{%- assign children_list = pages_list | where: "parent", page.title | where: "grand_parent",
|
||||
page.parent -%}
|
||||
{% for child in children_list %}
|
||||
<li>
|
||||
<a href="{{ child.url | absolute_url }}">{{ child.title }}</a>{% if child.summary %} - {{
|
||||
child.summary }}{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{% capture footer_custom %}
|
||||
{%- include footer_custom.html -%}
|
||||
{% endcapture %}
|
||||
{% if footer_custom != "" or site.last_edit_timestamp or site.gh_edit_link %}
|
||||
<hr>
|
||||
<footer>
|
||||
{% if site.back_to_top %}
|
||||
<p><a href="#top" id="back-to-top">{{ site.back_to_top_text }}</a></p>
|
||||
{% endif %}
|
||||
|
||||
{{ footer_custom }}
|
||||
|
||||
{% if site.last_edit_timestamp or site.gh_edit_link %}
|
||||
<div class="d-flex mt-2">
|
||||
{% if site.last_edit_timestamp and site.last_edit_time_format and page.last_modified_date %}
|
||||
<p class="text-small text-grey-dk-000 mb-0 mr-2">
|
||||
Page last modified: <span class="d-inline-block">{{ page.last_modified_date | date:
|
||||
site.last_edit_time_format }}</span>.
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if
|
||||
site.gh_edit_link and
|
||||
site.gh_edit_link_text and
|
||||
site.gh_edit_repository and
|
||||
site.gh_edit_branch and
|
||||
site.gh_edit_view_mode
|
||||
%}
|
||||
<p class="text-small text-grey-dk-000 mb-0">
|
||||
<a href="{{ site.gh_edit_repository }}/{{ site.gh_edit_view_mode }}/{{ site.gh_edit_branch }}{% if site.gh_edit_source %}/{{ site.gh_edit_source }}{% endif %}/{{ page.path }}"
|
||||
id="edit-this-page">{{ site.gh_edit_link_text }}</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</footer>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if site.search_enabled != false %}
|
||||
{% if site.search.button %}
|
||||
<a href="#" id="search-button" class="search-button">
|
||||
<svg viewBox="0 0 24 24" class="icon">
|
||||
<use xlink:href="#svg-search"></use>
|
||||
</svg>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
<div class="search-overlay"></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<script src='{{ "/assets/js/custom/cookies/cookies.js" | absolute_url }}'></script>
|
||||
{% include cookie_consent.html %}
|
||||
<script src='{{ "/assets/js/custom/scheme/colorscheme.js" | absolute_url }}'></script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
layout: default
|
||||
---
|
||||
|
||||
{{ content }}
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
layout: default
|
||||
---
|
||||
|
||||
{{ content }}
|
@ -1,16 +0,0 @@
|
||||
---
|
||||
layout: default
|
||||
---
|
||||
|
||||
<article id="post">
|
||||
<header class="post-header">
|
||||
<h1 class="post-title">{{ page.title }}</h1>
|
||||
<div class="post-date">{{ page.date | date: "%b %-d, %Y" }}</div>
|
||||
<ul class="post-categories">
|
||||
{% for category in page.categories %}
|
||||
<li class="post-category">{{ category }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</header>
|
||||
{{ content }}
|
||||
</article>
|
@ -1,7 +0,0 @@
|
||||
---
|
||||
layout: vendor/compress
|
||||
---
|
||||
|
||||
{% assign content_ = content | replace: '<table', '<div class="table-wrapper"><table' %}
|
||||
{% assign content_ = content_ | replace: '</table>', '</table></div>' %}
|
||||
{{ content_ }}
|
10
docs/_layouts/vendor/compress.html
vendored
10
docs/_layouts/vendor/compress.html
vendored
@ -1,10 +0,0 @@
|
||||
---
|
||||
# Jekyll layout that compresses HTML
|
||||
# v3.1.0
|
||||
# http://jch.penibelst.de/
|
||||
# © 2014–2015 Anatol Broder
|
||||
# MIT License
|
||||
---
|
||||
|
||||
{% capture _LINE_FEED %}
|
||||
{% endcapture %}{% if site.compress_html.ignore.envs contains jekyll.environment or site.compress_html.ignore.envs == "all" %}{{ content }}{% else %}{% capture _content %}{{ content }}{% endcapture %}{% assign _profile = site.compress_html.profile %}{% if site.compress_html.endings == "all" %}{% assign _endings = "html head body li dt dd optgroup option colgroup caption thead tbody tfoot tr td th" | split: " " %}{% else %}{% assign _endings = site.compress_html.endings %}{% endif %}{% for _element in _endings %}{% capture _end %}</{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _end %}{% endfor %}{% if _profile and _endings %}{% assign _profile_endings = _content | size | plus: 1 %}{% endif %}{% for _element in site.compress_html.startings %}{% capture _start %}<{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _start %}{% endfor %}{% if _profile and site.compress_html.startings %}{% assign _profile_startings = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.comments == "all" %}{% assign _comments = "<!-- -->" | split: " " %}{% else %}{% assign _comments = site.compress_html.comments %}{% endif %}{% if _comments.size == 2 %}{% capture _comment_befores %}.{{ _content }}{% endcapture %}{% assign _comment_befores = _comment_befores | split: _comments.first %}{% for _comment_before in _comment_befores %}{% if forloop.first %}{% continue %}{% endif %}{% capture _comment_outside %}{% if _carry %}{{ _comments.first }}{% endif %}{{ _comment_before }}{% endcapture %}{% capture _comment %}{% unless _carry %}{{ _comments.first }}{% endunless %}{{ _comment_outside | split: _comments.last | first }}{% if _comment_outside contains _comments.last %}{{ _comments.last }}{% assign _carry = false %}{% else %}{% assign _carry = true %}{% endif %}{% endcapture %}{% assign _content = _content | remove_first: _comment %}{% endfor %}{% if _profile %}{% assign _profile_comments = _content | size | plus: 1 %}{% endif %}{% endif %}{% assign _pre_befores = _content | split: "<pre" %}{% assign _content = "" %}{% for _pre_before in _pre_befores %}{% assign _pres = _pre_before | split: "</pre>" %}{% assign _pres_after = "" %}{% if _pres.size != 0 %}{% if site.compress_html.blanklines %}{% assign _lines = _pres.last | split: _LINE_FEED %}{% capture _pres_after %}{% for _line in _lines %}{% assign _trimmed = _line | split: " " | join: " " %}{% if _trimmed != empty or forloop.last %}{% unless forloop.first %}{{ _LINE_FEED }}{% endunless %}{{ _line }}{% endif %}{% endfor %}{% endcapture %}{% else %}{% assign _pres_after = _pres.last | split: " " | join: " " %}{% endif %}{% endif %}{% capture _content %}{{ _content }}{% if _pre_before contains "</pre>" %}<pre{{ _pres.first }}</pre>{% endif %}{% unless _pre_before contains "</pre>" and _pres.size == 1 %}{{ _pres_after }}{% endunless %}{% endcapture %}{% endfor %}{% if _profile %}{% assign _profile_collapse = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.clippings == "all" %}{% assign _clippings = "html head title base link meta style body article section nav aside h1 h2 h3 h4 h5 h6 hgroup header footer address p hr blockquote ol ul li dl dt dd figure figcaption main div table caption colgroup col tbody thead tfoot tr td th" | split: " " %}{% else %}{% assign _clippings = site.compress_html.clippings %}{% endif %}{% for _element in _clippings %}{% assign _edges = " <e;<e; </e>;</e>;</e> ;</e>" | replace: "e", _element | split: ";" %}{% assign _content = _content | replace: _edges[0], _edges[1] | replace: _edges[2], _edges[3] | replace: _edges[4], _edges[5] %}{% endfor %}{% if _profile and _clippings %}{% assign _profile_clippings = _content | size | plus: 1 %}{% endif %}{{ _content }}{% if _profile %} <table id="compress_html_profile_{{ site.time | date: "%Y%m%d" }}" class="compress_html_profile"> <thead> <tr> <td>Step <td>Bytes <tbody> <tr> <td>raw <td>{{ content | size }}{% if _profile_endings %} <tr> <td>endings <td>{{ _profile_endings }}{% endif %}{% if _profile_startings %} <tr> <td>startings <td>{{ _profile_startings }}{% endif %}{% if _profile_comments %} <tr> <td>comments <td>{{ _profile_comments }}{% endif %}{% if _profile_collapse %} <tr> <td>collapse <td>{{ _profile_collapse }}{% endif %}{% if _profile_clippings %} <tr> <td>clippings <td>{{ _profile_clippings }}{% endif %} </table>{% endif %}{% endif %}
|
@ -1,42 +0,0 @@
|
||||
---
|
||||
layout: about
|
||||
title: About
|
||||
permalink: /about/
|
||||
has_children: true
|
||||
nav_order: 5
|
||||
has_toc: false
|
||||
---
|
||||
|
||||
|
||||
EyeTrackVR developers are a group of people who are passionate about the field of augmented and virtual reality.
|
||||
{: .fs-5 .fw-300 }
|
||||
|
||||
## Key Members
|
||||
|
||||
Meet the Team!
|
||||
{: .fs-4 .fw-300 }
|
||||
<!-- To include people in this list please edit the appropriate yaml file in the _data directory-->
|
||||
{% include people/key_members/keymembers.html %}
|
||||
|
||||
<p style="page-break-after:always;"></p>
|
||||
|
||||
## Contributors
|
||||
|
||||
Individuals
|
||||
{: .fs-6 .fw-300 }
|
||||
<!-- To include people in this list please edit the appropriate yaml file in the _data directory-->
|
||||
{% include people/contributors/individuals.html %}
|
||||
|
||||
<p style="page-break-after:always;"></p>
|
||||
|
||||
## Philosophy
|
||||
|
||||
The [How to Build](/EyeTrackVR/how_to_build/) section of this website includes some of our teams own notes (not all of them are polished) that we disclose for other people to use.
|
||||
There, we hope you may find something useful to you.
|
||||
|
||||
We advocate the [Open Source model](https://en.wikipedia.org/wiki/Open-source_model).
|
||||
This is why we strive to make our work open to other people for consultation, replication and reuse.
|
||||
|
||||
Credits
|
||||
{: .fs-6 .fw-300 }
|
||||
{% include people/credits/credits.html %}
|
@ -1,19 +0,0 @@
|
||||
---
|
||||
layout: default
|
||||
title: How to build
|
||||
nav_order: 8
|
||||
has_children: true
|
||||
has_toc: true
|
||||
permalink: how_to_build
|
||||
---
|
||||
|
||||
So, you want eyetracking in vr, but don't want to _buy it_😷?
|
||||
{: .fs-5 .fw-300}
|
||||
|
||||
<i>Well, you've come to the right place then‼<i>
|
||||
{: .fs-6 .fw-400}
|
||||
|
||||
The following section of documentation will walk you through exactly how to build your very own eyetracking rig.
|
||||
{: .fs-5 .fw-300}
|
||||
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/cAuSjtW.gif" max-width="500" caption="This, could be your eye. Who knows ...." alt="img" %}
|
@ -1,42 +0,0 @@
|
||||
---
|
||||
layout: page
|
||||
title: Building the app from source
|
||||
permalink: /building-the-app/
|
||||
nav_order: 3
|
||||
parent: Software Guide
|
||||
---
|
||||
|
||||
## This guide will show how to build the app from source
|
||||
|
||||
{% include custom/alerts/Note.html content="This is NOT a required step, you do not need to build the app from source." %}
|
||||
|
||||
## Requirements:
|
||||
|
||||
- [x] [Python 3.11.0](https://www.python.org/downloads/release/python-3110/)
|
||||
- [x] [Poetry](https://python-poetry.org/)
|
||||
- [x] Windows/Linux PC
|
||||
|
||||
## Install Python
|
||||
EyetrackVR is currently using [Python 3.11.0](https://www.python.org/downloads/release/python-3110/) Before you continue, please install it.
|
||||
|
||||
## Installing Poetry
|
||||
|
||||
Since version `0.1.7` of EyeTrackVR, we have been using Poetry to manage app dependencies. To build the app, you must first install Poetry to fetch the required dependencies.
|
||||
|
||||
To install Poetry open Windows Powershell and run the following command `(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | py -`
|
||||
|
||||
[Poetry Documentation](https://python-poetry.org/docs/)
|
||||
|
||||
|
||||
## Install the required Python modules.
|
||||
|
||||
After cloning the project and installing Poetry, open a command prompt in the EyeTrackApp folder. Then run the command: `poetry install`
|
||||
|
||||
This should install all of the required modules.
|
||||
|
||||
## Build the app.
|
||||
|
||||
Now, you should be ready to build the app.
|
||||
With a command prompt open in the EyeTrackApp folder, run the command `poetry run pyinstaller eyetrackapp.spec`
|
||||
|
||||
Give it time to build the app. Once done, the app should be under `dist/eyetrackapp`
|
@ -1,9 +0,0 @@
|
||||
---
|
||||
layout: default
|
||||
title: Web-Forum
|
||||
nav_order: 1
|
||||
parent: Community Outreach
|
||||
has_children: false
|
||||
---
|
||||
|
||||
{% include custom/misc/comments.html url=page.url %}
|
@ -1,24 +0,0 @@
|
||||
---
|
||||
layout: page
|
||||
title: Configuring firmware
|
||||
permalink: /configure-firmware/
|
||||
nav_order: 2
|
||||
parent: Firmware Guide
|
||||
---
|
||||
|
||||
|
||||
## Once you have opened the project, you should see something on the left side like this.
|
||||
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/VZeI39I.png" max-width="500" caption="" alt="" %}
|
||||
|
||||
|
||||
## Open the `platformio.ini` file.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/ySzUMPO.png" max-width="500" caption="" alt="" %}
|
||||
|
||||
On lines 17 and 18 replace the placeholder text with your correct SSID (WiFi access point name), and password respectfully.
|
||||
|
||||
{% include custom/alerts/Note.html content="Make sure your wifi router has a 2.4 GHz band. While most do, this is not always the case. Setting each band, (5GHz, and 2.4GHz) to different SSIDs is recommended though not required." %}
|
||||
|
||||
Double check that you have correctly entered your WiFi credentials and that said wifi network has a 2.4GHz band.
|
||||
|
||||
## [Now, move on to uploading the firmware](https://redhawk989.github.io/EyeTrackVR/building-and-flashing-firmware-manually/)
|
@ -1,17 +0,0 @@
|
||||
---
|
||||
layout: page
|
||||
title: Socials
|
||||
permalink: /contact/
|
||||
nav_order: 2
|
||||
parent: Community Outreach
|
||||
---
|
||||
|
||||
# Contact Us
|
||||
|
||||
Please join our Discord for updates and any questions.
|
||||
|
||||
<div>
|
||||
<iframe id="discord-widget" src="https://discord.com/widget?id=946212245187199026&theme=light" width="350" height="500" allowtransparency="true" frameborder="0" sandbox="allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts" target="_blank"></iframe>
|
||||
</div>
|
||||
|
||||
<!-- [](https://discord.gg/kkXYbVykZX){:target="_blank" :alt="Discord"} -->
|
@ -1,41 +0,0 @@
|
||||
---
|
||||
layout: page
|
||||
title: How to create your own camera mount
|
||||
permalink: /creating-your-own-camera-mount/
|
||||
nav_order:
|
||||
parent: How to build
|
||||
---
|
||||
|
||||
## This page will include a basic rundown on how to create your own camera mount for a headset that may not have any existing community mounts.
|
||||
|
||||
So, you have a headset that does not have any mounts or none that work well for you. Here I will show some simple steps to get some form of a mount working.
|
||||
|
||||
## Step 1: Find a way to mount to your headsets lens.
|
||||
The easiest way to get started is to find a lens protector for your headset.
|
||||
Either go to a website like [Thingiverse](https://www.thingiverse.com/) or just do a search for "3d printed lens protector for {your headset here}"
|
||||
|
||||
Example: Here is a lens protector for the Quest 1/2 and Rift S [https://www.thingiverse.com/thing:3653631](https://www.thingiverse.com/thing:3653631)
|
||||
|
||||
## Step 2: Find a camera mount.
|
||||
Now, you need a way to attach the camera. We have a basic design that qdot created (taken from his mount) on the hardware GitHub [here](https://github.com/RedHawk989/EyeTrackVR-Hardware/blob/main/3d_Printed_Mounts/Basic_Mount_Components/basic_ETVR_camera_mount.stl)
|
||||
|
||||
Alternatively, you can create your own mount if you have the skills.
|
||||
|
||||
## Step 3: Place the camera mount where it will give a good camera angle.
|
||||
The "Ideal" location is a place that gives a good view of the pupil when looking to all extremes, the lower corners do a good job at getting there, or nearly there.
|
||||
|
||||
You want to put the camera as close to the headset's lens as possible to achieve the biggest view of the eye.
|
||||
I recommend looking at other headset mounts for [inspiration.](https://github.com/RedHawk989/EyeTrackVR-Hardware/tree/main/3d_Printed_Mounts)
|
||||
|
||||
## Step 4: Mount your LEDs.
|
||||
|
||||
You can either add parts to your mount for holding the LED boards or just glue them on. It's up to you and what works best for you, experiment!
|
||||
|
||||
## Step 5: Test everything!
|
||||
It is unlikely you will get a perfect mount on the first try. Print, test, adjust, and repeat until you have a satisfactory mount.
|
||||
Good luck!
|
||||
|
||||
## Step 6: Get your mounts listed!
|
||||
Send me the mount to be added to the docs here! You can upload it to Thingiverse or similar services, or just send me the .STLs via discord (Prohurtz#0001)
|
||||
|
||||
|
@ -1,42 +0,0 @@
|
||||
---
|
||||
layout: page
|
||||
title: Development Roadmap
|
||||
permalink: /dev-roadmap/
|
||||
nav_order: 2
|
||||
parent: About
|
||||
---
|
||||
|
||||
|
||||
# EyeTrackVR Development Roadmap
|
||||
|
||||
This will contain a list of features that are in progress, completed, and planned.
|
||||
{:.fs-5 .fw-300}
|
||||
|
||||
## Completed
|
||||
|
||||
- [x] Tracking algorithm
|
||||
- [x] Calibration
|
||||
- [x] GUI
|
||||
- [X] PCB Design for IR emitters
|
||||
- [X] Dual eye support
|
||||
- [X] Firmware
|
||||
- [X] Better documentation over things (setup, wiring etc.)
|
||||
|
||||
## In Progress
|
||||
|
||||
|
||||
- [ ] Variable eye openness tracking
|
||||
- [ ] Release of V1 to the masses
|
||||
- [ ] Auto ROI cropping
|
||||
- [ ] Auto threshold's
|
||||
- [ ] Setup WiFi credentials for ESPs through non-firmware means
|
||||
- [ ] Setup flashing of ESPs through anything other than VSC
|
||||
- [ ] New GUI
|
||||
- [ ] Power regulator board
|
||||
- [ ] New IR LED PCB (only for the power reg board)
|
||||
|
||||
## Planned
|
||||
|
||||
- [ ] Support for binary parameters
|
||||
- [ ] Dynamic foveated rendering via OpenXR (not a guarantee)
|
||||
- [ ] Custom ESP-CAM boards
|
@ -1,144 +0,0 @@
|
||||
---
|
||||
layout: page
|
||||
title: Installing and setting up the ETVR App
|
||||
permalink: /install-and-set-up-the-app/
|
||||
nav_order: 2
|
||||
parent: Software Guide
|
||||
---
|
||||
|
||||
|
||||
|
||||
# How to install, run and adjust the EyeTrackVR app.
|
||||
|
||||
### Step 1: Download the EyeTrackVR Installer and install the EyeTrackVR app.
|
||||
|
||||
Go to the latest [GitHub release here](https://github.com/RedHawk989/EyeTrackVR-Installer/releases/latest) and download the .zip
|
||||
|
||||
Extract the zip file and then run the .exe as administrator.
|
||||
You will be greeted with a window that looks like this:
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/olwRFYI.png" max-width="500" caption="" alt="" %}
|
||||
|
||||
By default, it will install to `C:\Program Files\EyeTrackVR` and create a shortcut on your desktop.
|
||||
Pressing the `Change Install Path` button will open up a window where you can navigate to an alternate install path.
|
||||
|
||||
Press `Install` to install the app.
|
||||
{% include custom/alerts/Note.html content=" The installer can also be used to update the app, just go through the install process again." %}
|
||||
|
||||
If it has been successfully installed it should change to look like this:
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/Ugzzgbh.png" max-width="500" caption="" alt="" %}
|
||||
|
||||
## Step 2: Run the EyeTrackVR app.
|
||||
|
||||
If the `Create Desktop Shortcut` option was checked you should see an icon on your desktop, double click it to run.
|
||||
|
||||
You then should be greeted with a GUI that looks like this:
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/z6V7A71.png" max-width="500" caption="" alt="" %}
|
||||
|
||||
## Step 3: Getting familiar with settings and terminology.
|
||||
|
||||
Let's go over some basic terminology you will find in the app.
|
||||
|
||||
Starting from the top:
|
||||
|
||||
### `Right eye`:
|
||||
Shows the right eye feed and settings only.
|
||||
|
||||
### `Left eye`:
|
||||
Shows the left eye feed and settings only.
|
||||
|
||||
### `Both eyes`:
|
||||
Shows both eyes' feed and settings.
|
||||
|
||||
### `Camera Address`:
|
||||
This is where you enter the IP address of your camera.
|
||||
Alternatively, it can be used to put the cam number for wired cameras or pass in a video file.
|
||||
|
||||
### `Tracking Mode`:
|
||||
This changes the GUI to the tracking mode where it outputs values.
|
||||
|
||||
### `Cropping Mode`:
|
||||
This is where you will crop out your eye.
|
||||
|
||||
### `Threshold`:
|
||||
This is used to cut out things that aren't dark like your pupil.
|
||||
|
||||
### `Rotation`:
|
||||
For our method to work best, you want your eye to be level.
|
||||
Use this slider to adjust it to where that is the case.
|
||||
|
||||
### `Restart Calibrationn`:
|
||||
This will start a calibration mode for your eye where you look to all extremes.
|
||||
|
||||
### `Recenter Eye`:
|
||||
This will recenter your eye to whatever point you are looking at.
|
||||
|
||||
|
||||
## Step 4: Adding your cameras to the software and configuring them.
|
||||
Power your ESPs and find what the IP address is for your right eye. This can be done by opening both Cameras in a browser and then holding your finger over your right eye camera.
|
||||
|
||||
Copy that IP address and then close the browser tab with it open.
|
||||
|
||||
Enter that IP address into the app's `Camera Address` field and press the `Save and Restart Tracking` button.
|
||||
|
||||
Don't see your camera feed? That's because we haven't set an ROI.
|
||||
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/MJb2h74.png" max-width="500" caption="See the Awating Eye Cropping Settings text?" alt="" %}
|
||||
|
||||
Now press the `Cropping Mode` button.
|
||||
You should see a feed of your camera.
|
||||
|
||||
Put your headset on and use an application to see your desktop. (Virtual desktop, SteamVR desktop, etc.)
|
||||
|
||||
You should see something like this:
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/1pNYITS.png" max-width="500" caption=":O It's my eye!" alt="" %}
|
||||
|
||||
Now, Draw a rectangle that selects your eye.
|
||||
|
||||
A good example of an ROI
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/HZSvFBv.png" max-width="500" caption="" alt="" %}
|
||||
|
||||
Head back over to the `Tracking mode`.
|
||||
|
||||
We will now adjust our rotation by moving the `Rotation` slider.
|
||||
|
||||
From this:
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/xXTB3sM.png" max-width="500" caption="It's crooked!" alt="" %}
|
||||
|
||||
To this:
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/blsrpCX.png" max-width="500" caption="Much better" alt="" %}
|
||||
|
||||
Now we will adjust our threshold.
|
||||
|
||||
Continuing with your headset on, move the slider all the way up.
|
||||
start slowly backing it off until mainly only your pupil is being visualized in the threshold viewer.
|
||||
|
||||
Example of a threshold being too low:
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/30fFadH.png" max-width="500" caption="" alt="" %}
|
||||
|
||||
Example of too high of a threshold:
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/ZjpKfCV.png" max-width="500" caption="" alt="" %}
|
||||
|
||||
Example of a good threshold:
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/KPUn8S1.png" max-width="500" caption="" alt="" %}
|
||||
|
||||
Repeat everything in this step for your left eye.
|
||||
|
||||
## Step 5: Calibrating your eyes.
|
||||
|
||||
Once your eye is trackable by the software we need to calibrate it.
|
||||
|
||||
Press the `Restart Calibration` button and look around.
|
||||
The important part is that you look to all extremes, all the way up, left, etc.
|
||||
Once you have done so, wait for the `Mode` to say `Tracking`
|
||||
|
||||
The next step is to center your eye.
|
||||
|
||||
Look straight forward and press the `Recenter Eye` button.
|
||||
|
||||
Your eye is now fully calibrated.
|
||||
|
||||
Repeat for your other eye.
|
||||
{% include custom/alerts/Note.html content=" To best center both eyes, look at one spot and hit the 'Recenter Eye' button for each eye without moving your eyes." %}
|
||||
|
||||
|
||||
## See anything outdated on this guide? Let me know! `Prohurtz#0001`
|
@ -1,9 +0,0 @@
|
||||
---
|
||||
layout: default
|
||||
title: FAQ
|
||||
nav_order: 14
|
||||
has_children: false
|
||||
permalink: /faq/
|
||||
---
|
||||
|
||||
{% include custom/FAQ/faq_template.html type="general" %}
|
@ -1,36 +0,0 @@
|
||||
---
|
||||
layout: default
|
||||
title: Firmware Guide
|
||||
nav_order: 9
|
||||
has_children: true
|
||||
permalink: /setting-up-firmware/
|
||||
---
|
||||
|
||||
# What is this?
|
||||
|
||||
Firmware is the second part of the equation to get your trackers going. It lives on the ESP32 chip, and is responsible for streaming video data from the tracker.
|
||||
|
||||
# What should I download and where?
|
||||
|
||||
Current testing has been on our own solution called OpenIris, [found here](https://github.com/lorow/OpenIris). So far we have:
|
||||
|
||||
### Working right now
|
||||
|
||||
- [x] Basic stream in 60FPS at 248x248px in MJPEG in greyscale
|
||||
- [x] A basic HTTP server with API, which allows for better control of the stream and the camera settings
|
||||
- [x] Health checks - we know when something goes wrong and we can react to it
|
||||
- [x] OTA updates - we can update the firmware on the fly
|
||||
- [x] ROI selection for eye area - this feature hasn't been tested all that much yet.
|
||||
- [x] MDNS - so that the server itself will detect and communicate with the tracker without you doing anything.
|
||||
|
||||
### In development are
|
||||
|
||||
- [ ] Persistent storage for storing your settings on the device itself, this will also allow for saving multiple wifi networks!
|
||||
- [ ] LED status patterns - so that you know what's going on without plugging the tracker in to the PC
|
||||
- [ ] FEC encoding with packet injection for even faster streams!
|
||||
- [ ] Better OTA so that updates can be downloaded from github and pushed by the server to the tracker
|
||||
- [ ] CI/CD with github actions - so we can more seamlessly update the trackers
|
||||
|
||||
# How do download this?
|
||||
|
||||
[Follow the steps described here](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository)
|
@ -1,300 +0,0 @@
|
||||
---
|
||||
layout: page
|
||||
title: Full Build Guide
|
||||
permalink: /full-build-guide/
|
||||
nav_order: 1
|
||||
parent: How to build
|
||||
has_toc: true
|
||||
---
|
||||
|
||||
## This page will contain a step-by-step assembly guide.
|
||||
|
||||
### Table of contents:
|
||||
[Step 1 Make sure you have read the Things to know before you start guide](#step-1-make-sure-your-have-read-the-things-to-know-before-you-start-guide)
|
||||
|
||||
[Step 2: Order all the parts listed on our Parts list](#step-2-order-all-the-parts-listed-on-our-parts-list)
|
||||
|
||||
[Step 3: Wait for things to arrive.](#step-3-wait-for-things-to-arrive)
|
||||
|
||||
[Step 4: Gather up all of your hardware.](#step-4-gather-up-all-of-your-hardware)
|
||||
|
||||
[Step 5: Install external antennas or sheild ESP antenna with antistatic bag.](#step-5-install-external-antennas-or-shield-esp-antenna-with-an-antistatic-bag)
|
||||
|
||||
[Step 6: Attach cameras to ESPs.](#step-6-connect-esp-to-the-programmer-to-flash)
|
||||
|
||||
[Step 7: Connect ESP to the programmer to flash.](#step-7-connect-esp-to-the-programmer-to-flash)
|
||||
|
||||
[Step 8: Configure Visual Studio Code and prepare to flash the firmware.](#step-7-configure-visual-studio-code-and-prepare-to-flash-the-firmware)
|
||||
|
||||
[Step 9: Plug in your ESP and flash the firmware.](#step-8-plug-in-your-esp-and-flash-the-firmware)
|
||||
|
||||
[Step 10: Connect your power wires to a USB Type-A board.](#step-9-connect-your-power-wires-to-a-usb-type-a-board)
|
||||
|
||||
[Step 11: Cut wires for IR LEDs.](#step-10-cut-wires-for-ir-leds)
|
||||
|
||||
[Step 12: Twist the positive USB wire and positive IR LED wires together and tin them.](#step-11-twist-the-positive-usb-wire-and-positive-ir-led-wires-together-and-tin-them)
|
||||
|
||||
[Step 13: Solder the positive wire to ESP.](#step-12-solder-the-positive-wire-to-esp)
|
||||
|
||||
[Step 14: Solder the negative wire to ESP](#step-13-solder-the-negative-wire-to-esp)
|
||||
|
||||
[Step 15: Wire up the 2nd ESP.](#step-14-wire-up-the-2nd-esp)
|
||||
|
||||
[Step 16: Prepare to solder IR LED PCBs](#step-15-prepare-to-solder-ir-led-pcbs)
|
||||
|
||||
[Step 17: Solder resistors on PCB V3.](#step-17-solder-resistors-on-pcb-v3)
|
||||
|
||||
[Step 18: Wire up PCBs V3](#wire-up-the-pcbs-v3)
|
||||
|
||||
[Step 19: 3D print mounts.](#step-19-3d-print-mounts)
|
||||
|
||||
## Step 1: Make sure your have read the [Things to know before you start](https://redhawk989.github.io/EyeTrackVR/things-to-know) guide.
|
||||
This will give you a basic overview of the project's status and what to expect currently.
|
||||
|
||||
## Step 2: Order all the parts listed on our [Parts list](https://redhawk989.github.io/EyeTrackVR/parts-list/)
|
||||
Please take note of the fact that hardware still may change, although with more developments it seems like we are going to stick with current hardware.
|
||||
|
||||
## Step 3: Wait for things to arrive.
|
||||
Long shipping times from China are *f u n*.
|
||||
Please allow anywhere from 2 weeks to 2 months for everything to arrive.
|
||||
|
||||
## Step 4: Gather up all of your hardware.
|
||||
|
||||
Make sure you have at least the following:
|
||||
|
||||
- [x] 2 ESP 32 CAM boards
|
||||
- [x] 2 160 degree cameras
|
||||
- [x] 1 USB board to power your ESPs
|
||||
- [x] 1 Programmer board (buying an extra is reccomended)
|
||||
- [x] IR emitters, resistors, and preferably PCBs
|
||||
- [x] Lower gauge wire to power ESPs
|
||||
- [x] Higher gauge wire to power IR LEDs
|
||||
- [x] 3d printer to print mounts. (Buying them from some place like JLCPCB is also an option)
|
||||
- [x] Glue of some form, hot glue highly recommended.
|
||||
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/j18rRI7.jpg" max-width="400" caption="ESPs, cams, a programmer and a USB connector" alt="img of components" %}
|
||||
|
||||
|
||||
## Step 5: Install external antennas or shield ESP antenna with an antistatic bag.
|
||||
|
||||
Some ESP-CAM boards have issues with signal integrity, there are 2 things you can do to help/solve the issues.
|
||||
|
||||
The first option is to use an external antenna.
|
||||
|
||||
This is the best solution when it comes to the final result. If you have Vive/Tundra trackers, this is a **REQUIRED** step. The interference from the trackers will make your ESP stream unusable. An antistatic bag does not help in this case. Unfortunately, removing the antenna is not super easy, you have to either move a resistor or, remove it and bridge 2 solder pads. The image attached below shows the orientation of the pads that need to be connected for which mode. You can not bridge all connections and have both antennas active at the same time. The 0-ohm resistor does not need to be on the board, you can simply bridge the connections.
|
||||
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/OzpxFMD.png" max-width="400" caption="Image from: https://randomnerdtutorials.com/esp32-cam-connect-external-antenna/" alt="img" %}
|
||||
|
||||
Below is an example of bridging the connections and attaching an antenna.
|
||||
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/RIFpNqW.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
|
||||
<iframe width="500" height="300" src="https://www.youtube.com/embed/r4PsuWTFRBg" title="How to add an external antenna to ESP32-CAM board" frameborder="1" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
|
||||
The second option is to cover the ESP's antenna with an antistatic bag.
|
||||
This can help aid problems, and can completely solve them in some cases. Best of all, it is completely free! However, it should be noted that it performs worse than an external antenna and in certain cases will not solve the issue like if you have Vive trackers.
|
||||
|
||||
<iframe width="500" height="300" src="https://www.youtube.com/embed/wS4PS3Mw250" title="Covering an ESP32-CAM's antenna with anti-static bag" frameborder="0" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
|
||||
## Step 6: Attach cameras to ESPs.
|
||||
|
||||
Look at your ESP and locate the camera ribbon cable connector as circled below.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/T5asLGN.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
Flip the gray part up to allow the cameras to be connected. Do not force it, or shove objects into it to open, fingernails are fine.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/Z8b8Sin.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
Now slide in a camera, please note that the pins are facing down, you should only see the black part.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/dDBIi9j.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
Once the camera has been slid in, press the gray part of the connector back down. There will be a small amount of force but still be gentle.
|
||||
Note the ammount of black coming out of the connector.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/VnFi5XS.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
## Step 7: Connect ESP to the programmer to flash.
|
||||
Why flash before you have it assembled? It's simple, to make sure they actually work before you spend time soldering to them.
|
||||
|
||||
Slide your ESP into the programmer, and note the USB port goes away from the ESP's camera.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/LsLPAcd.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
## Step 8: Configure Visual Studio Code and prepare to flash the firmware.
|
||||
Check out our guide on [Setting up VS Code](https://redhawk989.github.io/EyeTrackVR/setting-up-firmware-enviroment/)
|
||||
|
||||
Once VS Code is set up, move on to the next step.
|
||||
|
||||
## Step 9: Plug in your ESP and flash the firmware.
|
||||
Our guide, [Building and uploading the firmware manually](https://redhawk989.github.io/EyeTrackVR/building-and-flashing-firmware-manually/) has steps on how to do this.
|
||||
After it has flashed, make sure you get a video stream in your browser, then power it down and flash your next ESP.
|
||||
|
||||
## Step 10: Connect your power wires to a USB Type-A board.
|
||||
|
||||
{% include custom/alerts/Warning.html content=" Powering from the programmer board will not work correctly. It delivers a lower voltage which results in dim LEDs and video artifacts which can both mess up tracking." %}
|
||||
|
||||
Get two pairs of wire, preferably two different colors, Cut them to length (56mm in my case) and twist together two for ground and two for 5V.
|
||||
Here I used speaker wire where the copper denotes positive and silver negative.
|
||||
Then, strip the wires to about 3mm of exposed wire.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/Cdu9lSN.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
## Step 11: Cut wires for IR LEDs.
|
||||
To find the optimal length, take a piece of wire and a marker and mock up your wire route, and mark the wire, cut it, then make another at the same size for the other eye.
|
||||
You will need 3 different cuts of wire. 2 short ones for connecting the 2 PCBs per eye together, 2 Longer ones for power, or ground and 2 slightly longer ones for power or ground for the LED near the camera at the bottom.
|
||||
|
||||
Once cut, strip them to around 4mm of exposed wire.
|
||||
|
||||
## Step 12: Twist the positive USB wire and positive IR LED wires together and tin them.
|
||||
Once twisted together add solder to keep them together. This makes the connection much easier.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/QlRrWNn.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
## Step 13: Solder the positive wire to ESP.
|
||||
Lay the wire on the outside of the 5V pin and apply solder.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/DhnmLBG.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
## Step 14: Solder the negative wire to ESP
|
||||
Repeat [Step 11](#step-12-twist-the-positive-usb-wire-and-positive-ir-led-wires-together-and-tin-them) but with the negative wires.
|
||||
|
||||
{% include custom/alerts/Note.html content="As a user in our discord has learned, you can short the IO12 pin with the ground pin without issues." %}
|
||||
|
||||
In the below example I put it on the top of the pin, It will be a week-ish joint but that's where glue comes in handy.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/PWA0gtq.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
## Step 15: Wire up the 2nd ESP.
|
||||
Repeat steps [12](#step-12-twist-the-positive-usb-wire-and-positive-ir-led-wires-together-and-tin-them)-[14](#step-14-solder-the-negative-wire-to-esp) with the 2nd ESP.
|
||||
|
||||
## Step 16: Prepare to solder IR LED PCBs.
|
||||
Get your magnifying glass out, it's time to solder very smol things.
|
||||
|
||||
Gather 4 PCBs, 4 IR LEDs, and either 4 ~350ohm.
|
||||
|
||||
357ohm resistors and V3 PCBs
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/0zXY79j.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
Here are the PCB pin-out labels:
|
||||
|
||||
V3
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/n1noWKq.png" max-width="400" caption="" alt="img" %}
|
||||
|
||||
LED labels:
|
||||
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/Ap8OAWY.png" max-width="400" caption="" alt="img" %}
|
||||
The green markings and notched corners mark the positive sides of the LEDs pictured above.
|
||||
|
||||
If you have different LEDs, please consult their datasheet.
|
||||
|
||||
Some terminology related to them:
|
||||
|
||||
5V: 5-volt power in.
|
||||
|
||||
GND: Ground or power out.
|
||||
|
||||
AR: After-Resistor this is to be used as the power in on the 2nd PCB in series as resistors are not needed on the 2nd PCB since they are on the 1st one.
|
||||
|
||||
SNG: Single resistor, use this as 5V in if you are using only 1 ~700ohm resistor on V3 boards (not recommended).
|
||||
|
||||
Negative: This marks the negative side of the LED.
|
||||
|
||||
Positive: This marks the positive side of the LED.
|
||||
|
||||
|
||||
## Step 18: Solder resistors on PCB V3.
|
||||
|
||||
You only need 1 PCB to have resistors per eye.
|
||||
|
||||
Tin the resistor pads. Note: in this example, I use too much solder, it should only be enough to lightly cover the pad.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/gb4etdB.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
|
||||
Next, grab a resistor and hold it on the pads.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/ev5QFch.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
While holding the resistor add solder to your soldering iron and apply it to the resistor.
|
||||
|
||||
I like to do this by having a piece of my solder stick up in the air and then put it on my iron that way.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/8jCQOHw.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
Flip the PCB and solder the other end.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/CHUb7Iv.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
Now repeat for the other one.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/jZYAm5O.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
|
||||
## Solder LEDs on PCB V3.
|
||||
Tin the LED pads.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/pjvLHJL.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
Orientate the LED and hold it in place.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/RbHZQhl.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
Solder one end.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/VyClWvp.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
Flip around and solder the other end.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/tFCQTqE.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
|
||||
|
||||
## Wire up the PCBs V3.
|
||||
|
||||
Pay attention to the direction of the LEDs on the PCBs.
|
||||
|
||||
If the green dot is facing inwards like in the picture below:
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/TiLTAms.png" max-width="400" caption="" alt="img" %}
|
||||
Use the following diagram:
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/2pFF3oM.png" max-width="500" caption="" alt="drawing" %}
|
||||
|
||||
If the green dot is facing outward like the picture below:
|
||||
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/bEq6Ww0.jpg" max-width="400" caption="" alt="img" %}
|
||||
|
||||
Use the following diagram:
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/ubIa1ir.png" max-width="400" caption="" alt="img" %}
|
||||
|
||||
|
||||
## Step 19: 3D print mounts.
|
||||
Head to the 3D printed parts section of the parts list [here.](https://redhawk989.github.io/EyeTrackVR/partslist/#3d-printed-parts)
|
||||
|
||||
Find which parts are for your headset and print them.
|
||||
Some may work better or worse, it is recommended to test all of them if there are multiple, print one of each kind.
|
||||
If none work, try making an edit yourself if you have the skills. If you have made a mount make sure to ping me, `Prohurtz#0001`, so I can add them to the list.
|
||||
|
||||
Having trouble getting them to fit? Try resizing the mounts up, or down a little to ensure a good fit.
|
||||
|
||||
There are 2 different types of mounts, how to secure the camera to each type will be documented below.
|
||||
|
||||
|
||||
### Type 1
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/a6ERUFx.png" max-width="500" caption="" alt="drawing" %}
|
||||
This uses a method of sliding in the camera. Generally, this is the recommended mounting method as it generally requires no glue.
|
||||
|
||||
|
||||
Place the camera into the mount
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/Wy89UWy.jpg" max-width="500" caption="" alt="drawing" %}
|
||||
|
||||
Slowly apply pressure inwards until the camera snaps into place.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/LtKOLWo.jpg" max-width="500" caption="" alt="drawing" %}
|
||||
|
||||
{% include custom/alerts/Note.html content="There is a good chance of breaking the mount when putting in the camera. If this happens you may be able to save the mount depending on where the break was. A small dab of hot glue around the camera is likely all that is needed." %}
|
||||
|
||||
### Type 2
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/9mty1bv.png" max-width="500" caption="" alt="drawing" %}
|
||||
This uses the method of gluing the camera.
|
||||
|
||||
Apply a bit of glue to the bottom of the camera mount
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/ArLO1ls.jpg" max-width="500" caption="" alt="drawing" %}
|
||||
|
||||
Place the camera on the mount.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/ZIecsMM.jpg" max-width="500" caption="" alt="drawing" %}
|
||||
|
||||
|
||||
## IR LED mounting.
|
||||
This again differs from mount to mount.
|
||||
|
||||
In some cases, there are designated spots for the LEDs to go.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/tYD1KKe.png" max-width="500" caption="" alt="drawing" %}
|
||||
|
||||
In others there are no specified spots, you will have to mess around to find what works best.
|
||||
This image shows the optimal/near-optimal position for the LEDs. Hot glue is your friend with this.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/3rCRU5A.jpg" max-width="500" caption="" alt="drawing" %}
|
||||
|
||||
Tip: Use rubbing alcohol to easily remove hot glue.
|
@ -1,10 +0,0 @@
|
||||
---
|
||||
layout: default
|
||||
title: Getting Started
|
||||
nav_order: 7
|
||||
has_children: true
|
||||
has_toc: true
|
||||
permalink: getting_started
|
||||
---
|
||||
|
||||
## Want to build an EyeTrackVR kit? This is where to start.
|
@ -1,86 +0,0 @@
|
||||
---
|
||||
layout: page
|
||||
title: Part List
|
||||
permalink: /parts-list/
|
||||
nav_order: 2
|
||||
parent: How to build
|
||||
---
|
||||
|
||||
## This page will include a basic part list for building an EyeTrackVR setup
|
||||
|
||||
{% include custom/alerts/Warning.html content=" Please note that no hardware has been fully set in stone, all purchases are at your loss if hardware changes" %}
|
||||
|
||||
{% include custom/alerts/Note.html content="It is recommended to source main parts from AliExpress as it is much cheaper." %}
|
||||
|
||||
{% include custom/alerts/Note.html content="It is good practice to buy more than needed in some cases, namely programmers and ESPs, this reduces the risk of a DOA (dead on arrival) causing a delay." %}
|
||||
|
||||
## Camera setup
|
||||
|
||||
- 2x ESP-CAM-32 modules [AliExpress here](https://a.aliexpress.com/_mKjL9Cq)
|
||||
|
||||
- 2x ov2640 160° fov IR / Night vers 75mm (850nm) [AliExpress here](https://a.aliexpress.com/_mrNbZww) or Amazon alternative cams that you will have to manually remove the IR filter on [here](https://www.amazon.com/Camera-Aideepen-Wide-Angle-Megapixel-Support/dp/B09XXPX4SP/)
|
||||
|
||||
- 1x ESP-CAM programmer/ MB [AliExpress here](https://a.aliexpress.com/_mPaPgPu)
|
||||
|
||||
Here is an Amazon link for 3 ESP32-Cams and programmers without the proper cameras [here](https://www.amazon.com/ESP32-CAM-ESP32-CAM-MB-Development-Compatible-Raspberry/dp/B097H2KLCH)
|
||||
|
||||
- 1x USB type-A male port to power both ESPs
|
||||
|
||||
[Bare breakout on AliExpress here](https://www.aliexpress.com/item/2255801092919590.html) or [Amazon here](https://www.amazon.com/10Gtek-DIP-Breakout-Adapter-2-54mm/dp/B09LC8WQCD/)
|
||||
|
||||
[Or one with a cover on AliExpress here](https://www.aliexpress.com/item/2251832820552545.html) or [Amazon here](https://www.amazon.com/Pigtail-Extension-Cables-Connector-Replacement/dp/B09ZQNJ2DJ/)
|
||||
|
||||
|
||||
- 1x Lower gauge wire to power ESPs
|
||||
[28 gauge wire from AliExpress here](https://a.aliexpress.com/_mK72cy6) or [Amazon here](https://www.amazon.com/Fermerry-Silicone-Stranded-Copper-Electrical/dp/B089CTT5X1/)
|
||||
|
||||
Reccommended:
|
||||
|
||||
- 2x External antennas for ESPs [AliExpress here](https://www.aliexpress.com/item/2255800868378357.html) or [Amazon here](https://www.amazon.com/gp/product/B09K3ZPY5Z/)
|
||||
## IR Emitters
|
||||
|
||||
- 4x Unfocused SMD IR emitters
|
||||
Recomended ones [from LCSC here](https://www.lcsc.com/product-detail/Infrared-IR-LEDs_XINGLIGHT-XL-3216HIRC-850_C965891.html).
|
||||
Alternative ones [from Digikey here](https://www.digikey.com/en/products/detail/inolux/IN-P32ZTIR/10384796). The difference between them is the ones from LCSC are rated for lower power, which means in the event of a short or mishap they should be safer, hence why they are recommended.
|
||||
{% include custom/alerts/Note.html content="The smaller ones can not be soldered at temps above 245C or they will burn. Low temp solder is recommended" %}
|
||||
|
||||
{% include custom/alerts/Warning.html content="(DO NOT BUY FOCUSED ONES! If they look like something you would find in a TV remote do not use them, if you aren't exactly sure what you are doing, buy them from the LCSC or Digikey link)" %}
|
||||
|
||||
|
||||
- 4x IR emitter PCBs (highly recommended) Gerber files and schematics located [here.](https://github.com/RedHawk989/EyeTrackVR-Hardware/tree/main/IR%20Emmitter)
|
||||
|
||||
- 2x 698-710ohm resistors or the more recommend way, 4x 350ohm 1206 SMD resistors for IR emitters (If you are not using PCBs for the emitters then buying regular through-hole resistors is acceptable)
|
||||
|
||||
- [357 ohm from Digikey here](https://www.digikey.com/en/products/detail/stackpole-electronics-inc/RMCF1206FT357R/1759919)
|
||||
- [348 ohm from LCSC here](https://lcsc.com/product-detail/Chip-Resistor-Surface-Mount_BOURNS-CR1206-FX-3480ELF_C205328.html)
|
||||
|
||||
or
|
||||
|
||||
- [698 ohm from LCSC here](https://lcsc.com/product-detail/Chip-Resistor-Surface-Mount_FOJAN-FRC1206F6980TS_C2933749.html)
|
||||
|
||||
I have a kit with the resistors, IR LEDs, and PCBs on [Tindie here.](https://www.tindie.com/products/eyetrackvr/eyetrackvr-pcbs-components-kit/)
|
||||
I also have a pre-soldered kit [also on Tindie here](https://www.tindie.com/products/eyetrackvr/assembled-eyetrackvr-ir-led-kit/)
|
||||
This ensures you get the correct IR emitter parts.
|
||||
If you are a Patreon please check out discount codes available to you, and also check out unit pricing.
|
||||
|
||||
- 1x Wire to power IR emitters
|
||||
[32 gauge wire from AliExpress here](https://a.aliexpress.com/_mK72cy6)
|
||||
|
||||
|
||||
|
||||
## Other parts
|
||||
|
||||
- 1x Hot glue or another form of glue. Hot glue gun from [AliExpress here](https://www.aliexpress.com/item/3256803968572059.html) or [Amazon here](https://www.amazon.com/Assark-Sticks-School-Repairs-20W/dp/B09FYWQ44L/)
|
||||
|
||||
- 1x Soldering iron and solder (lead-free solder highly recommended) Generic soldering iron from [AliExpress here](https://www.aliexpress.com/item/3256801448141079.html) or [Amazon here](https://www.amazon.com/Liouhoum-Auto-Sleep-Adjustable-Temperature-Thermostatic/dp/B08PZBPXLZ/ref=sr_1_9)
|
||||
|
||||
|
||||
{% include custom/3d_printed_parts/Parts.html %}
|
||||
|
||||
### Other Headsets
|
||||
|
||||
If you own another headset not listed above, that means there are no mounts designed for them yet. If you have basic skills in modeling or think up a solution to mount cams and emitters, please try to make a mount and then let us in the discord know so it can be added here. Any headset that can fit the camera is potentially compatible. If you are willing, give it a shot to design a mount for the rest of the community.
|
||||
|
||||
Check out our basic guide on making your own mount [here.](https://docs.eyetrackvr.dev/creating-your-own-camera-mount/)
|
||||
|
||||
{% include custom/alerts/Tip.html content="If you have a headset mount that is not listed above, please let us know in the discord so it can be added here" %}
|
@ -1,68 +0,0 @@
|
||||
---
|
||||
layout: page
|
||||
title: "Privacy Policy"
|
||||
permalink: /privacy/
|
||||
modified: 2022-03-05
|
||||
nav_exclude: true
|
||||
---
|
||||
|
||||
# Privacy Policy
|
||||
|
||||
The privacy of my visitors is extremely important. This Privacy Policy outlines the types of personal information that is received and collected and how it is used.
|
||||
|
||||
## Designation of the responsible authority
|
||||
|
||||
The persons responsible for data processing on this website are:
|
||||
|
||||
RedHawk989 & ZanzyTHEbar
|
||||
{: .fs-5 .fw-300 }
|
||||
|
||||
The responsible body(s) decides alone or jointly with others on the purposes and means of processing personal data (e.g. names, contact details, etc.).
|
||||
|
||||
## Log Files
|
||||
|
||||
Like many other websites, this site uses log files to help learn about when, from where, and how often traffic flows to this site. The information in these log files include:
|
||||
|
||||
- Internet Protocol addresses (IP)
|
||||
- Types of browser
|
||||
- Internet Service Provider (ISP)
|
||||
- Date and time stamp
|
||||
- Referring and exit pages
|
||||
- Number of clicks
|
||||
|
||||
All of this information is not linked to anything that is personally identifiable.
|
||||
|
||||
## Cookies and Web Beacons
|
||||
|
||||
I use cookies on this site to store limited information about how you interact with the site. In line with [EU legislation](https://gdpr.eu/cookies/), I have identified several different types of cookies:
|
||||
|
||||
- **Strictly necessary cookies**.
|
||||
- I set a cookie to store your acceptance of my cookie policy. This expires after 31 days.
|
||||
- **Preferences cookies** to remember your preferences. These are not used on this website.
|
||||
- **Statistics cookies** that allow me to see how my audience uses the website. I use:
|
||||
- Google Analytics
|
||||
- **Marketing cookies** to help advertisers deliver relevant content are not used on this website.
|
||||
|
||||
## Google Analytics
|
||||
|
||||
Google Analytics is a web analytics tool I use to help understand how visitors engage with this website. It reports website trends using cookies and web beacons without identifying individual visitors. Individual IP addresses are anonymized. You can read [Google Analytics Privacy Policy](http://www.google.com/analytics/learn/privacy.html).
|
||||
|
||||
### Objection to data collection
|
||||
|
||||
You can prevent the collection of your data by Google Analytics by clicking on the following link [https://tools.google.com/dlpage/gaoptout](https://tools.google.com/dlpage/gaoptout). An opt-out cookie is set to prevent the collection of your information on future visits to our site: Disable Google Analytics.
|
||||
|
||||
Details on how Google Analytics handles user data can be found in the Google privacy policy: [https://support.google.com/analytics/answer/6004245](https://support.google.com/analytics/answer/6004245).
|
||||
|
||||
### Demographic characteristics at Google Analytics
|
||||
|
||||
This website uses the function "demographic characteristics" of Google Analytics. It can be used to generate reports that contain information about the age, gender and interests of visitors to the site. This data comes from interest-based advertising by Google as well as from visitor data from third parties. It is not possible to assign the data to a specific person. You can deactivate this function at any time. You can do this through the ad settings in your Google Account or by generally prohibiting the collection of your data by Google Analytics, as explained in the section "Opting out of data collection".
|
||||
|
||||
## Google Web Fonts
|
||||
|
||||
This website uses Web Fonts from Google. The provider is Google Inc, 1600 Amphitheater Parkway, Mountain View, CA 94043, USA.
|
||||
|
||||
The use of Google Fonts allows me to present this website using my choice of fonts, regardless of the fonts that are installed locally. This is done by retrieving the Google Web Fonts from a Google server in the USA and the associated transfer of your data to Google. This data is your IP address and which page you have visited on this website. The use of Google Web Fonts is based on Art. 6 para. 1 lit. f DSGVO. As the operator of this website, I have a legitimate interest in the optimal display and transmission of my web presence.
|
||||
|
||||
The company Google is certified for the US-European data protection convention "Privacy Shield". This data protection agreement is intended to ensure compliance with the level of data protection applicable in the EU.
|
||||
|
||||
Details about Google Web Fonts can be found here: [https://www.google.com/fonts#AboutPlace:about](https://www.google.com/fonts#AboutPlace:about) and further information in the Google Privacy Policy: [https://policies.google.com/privacy/partners](https://policies.google.com/privacy/partners).
|
@ -1,56 +0,0 @@
|
||||
---
|
||||
layout: page
|
||||
title: Setup Visual Studio Code environment
|
||||
nav_order: 1
|
||||
permalink: /setting-up-firmware-enviroment/
|
||||
parent: Firmware Guide
|
||||
---
|
||||
|
||||
# Setting up the environment
|
||||
|
||||
This procedure will show how to prepare your system for uploading the firmware to your tracker.
|
||||
|
||||
## 1. Install Visual Studio Code
|
||||
|
||||
Download the [latest Visual Studio Code](https://code.visualstudio.com/download) and install it.
|
||||
|
||||
### Download
|
||||
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/jXPXIFz.gif" max-width="500" caption="" alt="" %}
|
||||
|
||||
### Install
|
||||
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/hAm3Zu0.gif" max-width="500" caption="" alt="" %}
|
||||
|
||||
## 2. Install PlatformIO IDE
|
||||
|
||||
Once Visual Studio Code is installed, open it and install [PlatformIO IDE for VSCode](https://marketplace.visualstudio.com/items?itemName=platformio.platformio-ide), an extension that will allow you to connect to the tracker, build and upload the firmware.
|
||||
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/ebV0IgT.gif" max-width="500" caption="" alt="" %}
|
||||
|
||||
## 3. Clone the firmware project
|
||||
|
||||
Make sure you close any current projects you have open or open a new window before moving forward with these steps.
|
||||
|
||||
1. Go to [https://github.com/lorow/OpenIris](https://github.com/lorow/OpenIris) and `clone` the latest version from the `main` branch.
|
||||
1. If you do not have `git` installed please install it from [here](https://git-scm.com/download/win).
|
||||
|
||||
2. Open Git Bash.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/DWO5vkE.png" max-width="500" caption="" alt="" %}
|
||||
|
||||
3. Change the directory to the directory that you want the firmware to be cloned. Ex: `cd C:\`
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/mWAVxtF.png" max-width="500" caption="" alt="" %}
|
||||
|
||||
4. Clone the repository by entering the command: `git clone https://github.com/lorow/OpenIris.git`
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/YbXpX7t.png" max-width="500" caption="" alt="" %}
|
||||
|
||||
|
||||
For more info about cloning please refer to [this documentation](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository)
|
||||
|
||||
_**Do not download as a zip**_ - please only properly clone the project, take note of the path you run the clone command in, this is where the files will be downloaded. When we open it in PlatformIO later, this path will be needed.
|
||||
|
||||
2. Open the firmware in VSCode by going to PlatformIO, selecting open, then navigating to `OpenIris/ESP` folder and opening it.
|
||||
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/c61Cpaz.gif" max-width="500" caption="" alt="" %}
|
||||
|
||||
_This is an adaptation from SlimeVR. Credit goes to the SlimeVR team [adapted from here](https://docs.slimevr.dev/firmware/setup-and-install.html)_
|
@ -1,10 +0,0 @@
|
||||
---
|
||||
layout: default
|
||||
title: Software Guide
|
||||
nav_order: 10
|
||||
has_toc: True
|
||||
has_children: True
|
||||
permalink: /software-guide/
|
||||
---
|
||||
|
||||
# How to install, setup, and build from source the EyeTrackApp.
|
@ -1,10 +0,0 @@
|
||||
---
|
||||
layout: default
|
||||
title: Community Outreach
|
||||
nav_order: 6
|
||||
has_children: true
|
||||
permalink: suggestions.html
|
||||
has_toc: false
|
||||
---
|
||||
|
||||
{% include custom/misc/googleform.html %}
|
@ -1,28 +0,0 @@
|
||||
---
|
||||
layout: page
|
||||
title: Things to know before you start
|
||||
permalink: /things-to-know
|
||||
nav_order: 1
|
||||
parent: Getting Started
|
||||
---
|
||||
|
||||
## This page will be an overview of things to know and understand before you start this project.
|
||||
|
||||
|
||||
### Software is not final.
|
||||
Bugs can and will occur which may hinder the experience or useability at times.
|
||||
Do not expect 100% reliable and perfect function. Not all features are fully developed yet.
|
||||
|
||||
### Firmware may have user difficulties.
|
||||
Our firmware has not been tested widely so issues may creep up.
|
||||
|
||||
### IR emitters are dangerous.
|
||||
If handled wrong or precautions are ignored you can and will cause damage to your eyes. Please make sure to only buy linked ones or ones with specs that match exactly. We will not be responsible for damaged caused if you go your own route.
|
||||
|
||||
### Documentation may be incomplete.
|
||||
Important steps may be missing.
|
||||
|
||||
### You will need to set up your avatar to use this.
|
||||
This will require some basic Unity knowledge and owning your own avatar.
|
||||
|
||||
### Once you have acknowledged the items above, move on to the [Full Build Guide](https://redhawk989.github.io/EyeTrackVR/full-build-guide/)
|
@ -1,93 +0,0 @@
|
||||
---
|
||||
layout: page
|
||||
title: Building and uploading the firmware manually
|
||||
permalink: /building-and-flashing-firmware-manually/
|
||||
nav_order: 3
|
||||
parent: Firmware Guide
|
||||
---
|
||||
|
||||
# Building and uploading the firmware manually
|
||||
|
||||
Uploading your firmware must initially be done over cable. Once you have the tracker connected to your WiFi after your first firmware update, you can opt to use OTA in the future.
|
||||
|
||||
## 1. Connect your tracker to your PC via the programmer.
|
||||
|
||||
First, connect your ESP32-Cam to your programmer. In the case of the ESP32-Cam-MB board, it's as simple as sticking it into the socket the way it came in the package and then connecting it to your PC with a micro-USB cable. In some cases, there is a button labeled IOO on the programmer. If that button exists make sure to hold it in while you plug the programmer into your pc, once plugged in you can release the button.
|
||||
|
||||
In the case of an FTDI programmer, the steps aren't as easy, so grab [this guide](https://randomnerdtutorials.com/program-upload-code-esp32-cam/) for how to set it up.
|
||||
|
||||
## 2. Build your firmware
|
||||
|
||||
1. Press the build button at the bottom of Visual Studio Code.
|
||||
|
||||
This builds the firmware, but does not send it to the ESP yet.
|
||||
|
||||

|
||||
|
||||
## 3. Upload your firmware
|
||||
|
||||
- If you are using the OTA method, first make sure the tracker you wish to flash is turned on.
|
||||
|
||||
- Once the firmware has been built, press the upload button to upload the firmware.
|
||||
|
||||
This sends the firmware to the ESP.
|
||||

|
||||
|
||||
{% include custom/alerts/Note.html content="The MB board does the resetting for you, so if you're using the FTDI programmer, follow the guide linked above (the one from randomnerdtutorials)" %}
|
||||
|
||||
- If the upload is successful, you should get an output that looks like this:
|
||||
|
||||

|
||||
|
||||
Congratulations! You have now successfully uploaded the firmware to your EyeTrackVR Tracker!
|
||||
|
||||
If you have trouble with uploading your firmware over cable check the following:
|
||||
|
||||
1. Make sure your USB cable from the tracker is plugged firmly into your PC.
|
||||
2. Make sure that your USB cable is a data and charging cable (it is suggested you try other cables or devices with the cable).
|
||||
3. Make sure that your drivers are up-to-date.
|
||||
4. Some ports might not work, try other ones.
|
||||
|
||||
Additionally, this can be caused by software hogging COM ports (**VSCode and Cura can be the cause of this**).
|
||||
|
||||
## Uploading via OTA
|
||||
|
||||
Once you have successfully connected your trackers to your WiFi, you can use OTA to handle all future firmware updates.
|
||||
|
||||
1. Retrieve the IP of the tracker you wish to flash. The IP can be found through network monitoring applications, or by viewing tracker output in a serial monitor.
|
||||
2. In `platformio.ini` file uncomment the following lines in Visual Studio Code by removing the `;`:
|
||||
|
||||
```ini
|
||||
;upload_protocol = espota
|
||||
;upload_port = 192.168.1.49
|
||||
```
|
||||
|
||||
1. Change the value of upload_port to the IP address retrieved during the first step.
|
||||
1. Turn the tracker you wish to flash off and then on again.
|
||||
1. Wait around 5 seconds.
|
||||
1. Press the upload button to upload the firmware.<br>
|
||||

|
||||
1. Repeat for as many trackers as you need.
|
||||
|
||||
## Finding the IP address of your tracker
|
||||
|
||||
Connect your tracker to your PC and then open a serial monitor in VSC by pressing the "plug" icon.
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/dSPSpkY.png" max-width="500" caption="" alt="img" %}
|
||||
|
||||
Now, press the restart button on the esp itself.
|
||||
watch the monitor for output like this:
|
||||
|
||||
{% include custom/images/image_2.html url="https://i.imgur.com/PoHP3NC.png" max-width="600" caption="" alt="img" %}
|
||||
|
||||
The text, highlighted in green for demonstration, is the stream address of the camera. Take note of this for input into the software.
|
||||
|
||||
Keep in mind while testing and getting set up, the ESP can only have one client, to use the camera in the app, make sure you close the browser tab you tested it in.
|
||||
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If you encountered an issue while following these steps check the [FAQ.](https://redhawk989.github.io/EyeTrackVR/faq/)
|
||||
|
||||
If you don't find an answer to your question there ask in **#questions** channel in [the discord](https://discord.gg/kkXYbVykZX), we will be happy to help.
|
||||
|
||||
*Adapted from the SlimeVR docs, Credit goes to the SlimeVR team [here](https://docs.slimevr.dev/firmware/setup-and-install.html)*
|
@ -1,15 +0,0 @@
|
||||
---
|
||||
layout: default
|
||||
title: VR Chat Avatar Setup
|
||||
nav_order: 12
|
||||
has_children: false
|
||||
permalink: /vrc-avatar-setup/
|
||||
---
|
||||
|
||||
# How to set up your avatar for eye tracking:
|
||||
|
||||
Currently, the best resource is the [VRC Face Tracking GitHub](https://github.com/benaclejames/VRCFaceTracking/wiki/Eye-Tracking-Setup) and [Discord](https://discord.gg/Fh4FNehzKn).
|
||||
|
||||
I hope to have a good video available from a community member that shows and explains the process eventually.
|
||||
|
||||
{% include custom/alerts/Note.html content="We currently only support float parameters, please adjust your setup accordingly" %}
|
@ -1,191 +0,0 @@
|
||||
@import url('https://fonts.googleapis.com/css?family=Montserrat:400,700');
|
||||
//vars
|
||||
$blue: hsl(190, 50%, 50%);
|
||||
$green: hsl(150, 50%, 50%);
|
||||
$dark-blue: hsl(190, 50%, 45%);
|
||||
$white: #fff;
|
||||
$black: #111;
|
||||
$off-black: #222;
|
||||
$soft-corners: 0.3rem;
|
||||
$underline: linear-gradient(to bottom, transparent 95%, $black 95%);
|
||||
$underline-light: linear-gradient(to bottom, transparent 95%, $white 95%);
|
||||
|
||||
//mixins
|
||||
@mixin bs($d: 5px, $a: 0.3) {
|
||||
box-shadow: 0 $d $d rgba(0, 0, 0, $a);
|
||||
}
|
||||
|
||||
@mixin bg-gradient($col1, $col2) {
|
||||
background: linear-gradient(to top, $col1 0%, $col2 * 1.5 100%);
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
background: $black;
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
}
|
||||
|
||||
.wrap {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
|
||||
color: $white;
|
||||
}
|
||||
.name--header {
|
||||
height: 10%;
|
||||
width: 100%;
|
||||
background: $dark-blue;
|
||||
font-size: 200%;
|
||||
text-shadow: 0px 0px 5px rgba(0, 0, 0, 0.4);
|
||||
color: $white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 2rem 1rem;
|
||||
border-bottom: 0.3rem solid $white;
|
||||
@include bs();
|
||||
justify-content: space-between;
|
||||
|
||||
& .name {
|
||||
font-weight: 500;
|
||||
}
|
||||
& .discord {
|
||||
font-size: 50%;
|
||||
& a {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.channels {
|
||||
margin: 1rem;
|
||||
@include bs();
|
||||
display: block;
|
||||
&--header {
|
||||
font-size: 150%;
|
||||
font-weight: 500;
|
||||
color: $white;
|
||||
padding: 1rem;
|
||||
@include bg-gradient($blue, $blue);
|
||||
border-top-left-radius: $soft-corners;
|
||||
border-top-right-radius: $soft-corners;
|
||||
}
|
||||
&--body {
|
||||
background: $off-black;
|
||||
margin: 0;
|
||||
padding: 1rem;
|
||||
border-bottom-left-radius: $soft-corners;
|
||||
border-bottom-right-radius: $soft-corners;
|
||||
}
|
||||
}
|
||||
.channel--name {
|
||||
margin: 0.3rem 0;
|
||||
padding: 0.2rem 0;
|
||||
background: $underline-light;
|
||||
}
|
||||
.users {
|
||||
margin: 1rem;
|
||||
@include bs();
|
||||
display: block;
|
||||
flex-direction: column;
|
||||
|
||||
&--header {
|
||||
font-size: 150%;
|
||||
font-weight: 500;
|
||||
@include bg-gradient($green, $green);
|
||||
color: $white;
|
||||
padding: 1rem;
|
||||
border-top-left-radius: $soft-corners;
|
||||
border-top-right-radius: $soft-corners;
|
||||
}
|
||||
&--body {
|
||||
background: $off-black;
|
||||
margin: 0;
|
||||
padding: 1rem;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
border-bottom-left-radius: $soft-corners;
|
||||
border-bottom-right-radius: $soft-corners;
|
||||
}
|
||||
}
|
||||
.user {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
align-items: center;
|
||||
font-size: 110%;
|
||||
margin: 0.5rem 0;
|
||||
background: $underline;
|
||||
padding: 0.3rem;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
&--image {
|
||||
width: 100%;
|
||||
border-radius: 100%;
|
||||
user-select: none;
|
||||
}
|
||||
& .username {
|
||||
margin: 0 0.5rem;
|
||||
position: relative;
|
||||
}
|
||||
& .bot--tag {
|
||||
order: 4;
|
||||
font-size: 50%;
|
||||
background: #7289da;
|
||||
padding: 0.2rem;
|
||||
border-radius: 0.1rem;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
.user--status {
|
||||
$size: 0.8rem;
|
||||
height: $size;
|
||||
width: $size;
|
||||
border-radius: 100%;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
.status--online {
|
||||
background: #43b581;
|
||||
}
|
||||
.status--idle {
|
||||
background: #faa61a;
|
||||
}
|
||||
.status--dnd {
|
||||
background: #f04747;
|
||||
}
|
||||
.image--wrap {
|
||||
$size: 2.5rem;
|
||||
background: pink;
|
||||
position: relative;
|
||||
border-radius: 100%;
|
||||
height: $size;
|
||||
width: $size;
|
||||
}
|
||||
.user--game {
|
||||
order: 5;
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: flex-end;
|
||||
position: relative;
|
||||
font-size: 75%;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
ul,
|
||||
li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
//
|
||||
// Base element style overrides
|
||||
//
|
||||
// stylelint-disable selector-no-type, selector-max-type
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
::selection {
|
||||
color: $white;
|
||||
background: $link-color;
|
||||
}
|
||||
|
||||
html {
|
||||
@include fs-4;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: $body-font-family;
|
||||
font-size: inherit;
|
||||
line-height: $body-line-height;
|
||||
color: $body-text-color;
|
||||
background-color: $body-background-color;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl,
|
||||
pre,
|
||||
address,
|
||||
blockquote,
|
||||
table,
|
||||
div,
|
||||
hr,
|
||||
form,
|
||||
fieldset,
|
||||
noscript .table-wrapper {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1em;
|
||||
font-weight: 500;
|
||||
line-height: $body-heading-line-height;
|
||||
color: $body-heading-color;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $link-color;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:not([class]) {
|
||||
text-decoration: none;
|
||||
background-image: linear-gradient($border-color 0%, $border-color 100%);
|
||||
background-repeat: repeat-x;
|
||||
background-position: 0 100%;
|
||||
background-size: 1px 1px;
|
||||
|
||||
&:hover {
|
||||
background-image: linear-gradient(
|
||||
rgba($link-color, 0.45) 0%,
|
||||
rgba($link-color, 0.45) 100%
|
||||
);
|
||||
background-size: 1px 1px;
|
||||
}
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: $mono-font-family;
|
||||
font-size: 0.75em;
|
||||
line-height: $body-line-height;
|
||||
}
|
||||
|
||||
figure,
|
||||
pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
hr {
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: $sp-6 0;
|
||||
background-color: $border-color;
|
||||
border: 0;
|
||||
}
|
@ -1,180 +0,0 @@
|
||||
//
|
||||
// Buttons and things that look like buttons
|
||||
//
|
||||
// stylelint-disable color-named
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
padding-top: 0.3em;
|
||||
padding-right: 1em;
|
||||
padding-bottom: 0.3em;
|
||||
padding-left: 1em;
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
font-weight: 500;
|
||||
line-height: 1.5;
|
||||
color: $link-color;
|
||||
text-decoration: none;
|
||||
vertical-align: baseline;
|
||||
cursor: pointer;
|
||||
background-color: $base-button-color;
|
||||
border-width: 0;
|
||||
border-radius: $border-radius;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12), 0 3px 10px rgba(0, 0, 0, 0.08);
|
||||
appearance: none;
|
||||
|
||||
&:focus {
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 3px rgba(blue, 0.25);
|
||||
}
|
||||
|
||||
&:focus:hover,
|
||||
&.selected:focus {
|
||||
box-shadow: 0 0 0 3px rgba(blue, 0.25);
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&.zeroclipboard-is-hover {
|
||||
color: darken($link-color, 2%);
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&.zeroclipboard-is-hover,
|
||||
&.zeroclipboard-is-active {
|
||||
text-decoration: none;
|
||||
background-color: darken($base-button-color, 1%);
|
||||
}
|
||||
|
||||
&:active,
|
||||
&.selected,
|
||||
&.zeroclipboard-is-active {
|
||||
background-color: darken($base-button-color, 3%);
|
||||
background-image: none;
|
||||
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
&.selected:hover {
|
||||
background-color: darken(#dcdcdc, 5%);
|
||||
}
|
||||
|
||||
&:disabled,
|
||||
&.disabled {
|
||||
&,
|
||||
&:hover {
|
||||
color: rgba(102, 102, 102, 0.5);
|
||||
cursor: default;
|
||||
background-color: rgba(229, 229, 229, 0.5);
|
||||
background-image: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-outline {
|
||||
color: $link-color;
|
||||
background: transparent;
|
||||
box-shadow: inset 0 0 0 2px $grey-lt-300;
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&.zeroclipboard-is-hover,
|
||||
&.zeroclipboard-is-active {
|
||||
color: darken($link-color, 4%);
|
||||
text-decoration: none;
|
||||
background-color: transparent;
|
||||
box-shadow: inset 0 0 0 3px $grey-lt-300;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
box-shadow: inset 0 0 0 2px $grey-dk-100, 0 0 0 3px rgba(blue, 0.25);
|
||||
}
|
||||
|
||||
&:focus:hover,
|
||||
&.selected:focus {
|
||||
box-shadow: inset 0 0 0 2px $grey-dk-100;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
@include btn-color($white, $btn-primary-color);
|
||||
}
|
||||
|
||||
.btn-mode {
|
||||
@include btn-color($white, $btn-primary-color);
|
||||
text-transform: uppercase;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 11px;
|
||||
margin-top: 17px;
|
||||
box-shadow: rgba(50, 50, 93, 0.25) 0px 50px 100px -20px, rgba(0, 0, 0, 0.3) 0px 30px 60px -30px, rgba(10, 37, 64, 0.35) 0px -2px 6px 0px inset;
|
||||
}
|
||||
|
||||
.btn-mode:active {
|
||||
background-color: #5739ce;
|
||||
background-image: linear-gradient(#5739ce, #6f55d5);
|
||||
box-shadow: rgba(50, 50, 93, 0.25) 0px 30px 60px -12px inset, rgba(0, 0, 0, 0.3) 0px 18px 36px -18px inset;
|
||||
}
|
||||
|
||||
.btn-github {
|
||||
@include btn-color($grey-dk-300, $white);
|
||||
text-transform: uppercase;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 11px;
|
||||
margin-top: 17px;
|
||||
box-shadow: rgba(50, 50, 93, 0.25) 0px 50px 100px -20px, rgba(0, 0, 0, 0.3) 0px 30px 60px -30px, rgba(10, 37, 64, 0.35) 0px -2px 6px 0px inset;
|
||||
}
|
||||
|
||||
.btn-github:active {
|
||||
background-color: $white;
|
||||
background-image: linear-gradient($white, rgb(193, 185, 185));
|
||||
box-shadow: rgba(50, 50, 93, 0.25) 0px 30px 60px -12px inset, rgba(0, 0, 0, 0.3) 0px 18px 36px -18px inset;
|
||||
}
|
||||
|
||||
.btn-arduino {
|
||||
@include btn-color($white, #2f9fa4);
|
||||
text-transform: uppercase;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 11px;
|
||||
margin-top: 17px;
|
||||
box-shadow: rgba(50, 50, 93, 0.25) 0px 50px 100px -20px, rgba(0, 0, 0, 0.3) 0px 30px 60px -30px, rgba(10, 37, 64, 0.35) 0px -2px 6px 0px inset;
|
||||
}
|
||||
|
||||
.btn-arduino:active {
|
||||
background-color: $white;
|
||||
background-image: linear-gradient(#2f9fa4, #206d71);
|
||||
box-shadow: rgba(50, 50, 93, 0.25) 0px 30px 60px -12px inset, rgba(0, 0, 0, 0.3) 0px 18px 36px -18px inset;
|
||||
}
|
||||
|
||||
.btn-discord {
|
||||
@include btn-color($white, #7289da);
|
||||
text-transform: uppercase;
|
||||
background-color: $white;
|
||||
background-image: linear-gradient(#7289da, #7289da);
|
||||
border-radius: 8px;
|
||||
margin-bottom: 11px;
|
||||
margin-top: 17px;
|
||||
box-shadow: rgba(50, 50, 93, 0.25) 0px 50px 100px -20px, rgba(0, 0, 0, 0.3) 0px 30px 60px -30px, rgba(10, 37, 64, 0.35) 0px -2px 6px 0px inset;
|
||||
}
|
||||
|
||||
.btn-discord:active {
|
||||
background-color: $white;
|
||||
background-image: linear-gradient(#7289da, #7289da);
|
||||
box-shadow: rgba(50, 50, 93, 0.25) 0px 30px 60px -12px inset, rgba(0, 0, 0, 0.3) 0px 18px 36px -18px inset;
|
||||
}
|
||||
|
||||
.btn-purple {
|
||||
@include btn-color($white, $purple-100);
|
||||
}
|
||||
|
||||
.btn-blue {
|
||||
@include btn-color($white, $blue-000);
|
||||
}
|
||||
|
||||
.btn-green {
|
||||
@include btn-color($white, $green-100);
|
||||
}
|
@ -1,340 +0,0 @@
|
||||
//
|
||||
// Code and syntax highlighting
|
||||
//
|
||||
// stylelint-disable selector-no-qualifying-type, declaration-block-semicolon-newline-after,declaration-block-single-line-max-declarations, selector-no-type, selector-max-type
|
||||
|
||||
code {
|
||||
padding: 0.2em 0.15em;
|
||||
font-weight: 400;
|
||||
background-color: $code-background-color;
|
||||
border: $border $border-color;
|
||||
border-radius: $border-radius;
|
||||
}
|
||||
|
||||
// Avoid appearance of dark border around visited code links in Safari
|
||||
a:visited code {
|
||||
border-color: $border-color;
|
||||
}
|
||||
|
||||
// Content structure for highlighted code blocks using fences or Liquid
|
||||
//
|
||||
// ```[LANG]...```, no kramdown line_numbers:
|
||||
// div.[language-LANG.]highlighter-rouge > div.highlight > pre.highlight > code
|
||||
//
|
||||
// ```[LANG]...```, kramdown line_numbers = true:
|
||||
// div.[language-LANG.]highlighter-rouge > div.highlight > pre.highlight > code
|
||||
// > div.table-wrapper > table.rouge-table > tbody > tr
|
||||
// > td.rouge-gutter.gl > pre.lineno
|
||||
// | td.rouge-code > pre
|
||||
//
|
||||
// {% highlight LANG %}...{% endhighlight %}:
|
||||
// figure.highlight > pre > code.language-LANG
|
||||
//
|
||||
// {% highlight LANG linenos %}...{% endhighlight %}:
|
||||
// figure.highlight > pre > code.language-LANG
|
||||
// > div.table-wrapper > table.rouge-table > tbody > tr
|
||||
// > td.gutter.gl > pre.lineno
|
||||
// | td.code > pre
|
||||
//
|
||||
// fix_linenos removes the outermost pre when it encloses table.rouge-table
|
||||
//
|
||||
// See docs/index-test.md for some tests.
|
||||
//
|
||||
// No kramdown line_numbers: fences and Liquid highlighting look the same.
|
||||
// Kramdown line_numbers = true: fences have a wider gutter than with Liquid?
|
||||
|
||||
// ```[LANG]...```
|
||||
div.highlighter-rouge {
|
||||
padding: $sp-3;
|
||||
margin-top: 0;
|
||||
margin-bottom: $sp-3;
|
||||
overflow-x: auto;
|
||||
background-color: $code-background-color;
|
||||
border-radius: $border-radius;
|
||||
box-shadow: none;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
||||
div.highlight,
|
||||
pre.highlight,
|
||||
code {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// {% highlight LANG %}...{% endhighlight %},
|
||||
// {% highlight LANG linenos %}...{% endhighlight %}:
|
||||
figure.highlight {
|
||||
padding: $sp-3;
|
||||
margin-top: 0;
|
||||
margin-bottom: $sp-3;
|
||||
background-color: $code-background-color;
|
||||
border-radius: $border-radius;
|
||||
box-shadow: none;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
||||
pre,
|
||||
code {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// ```[LANG]...```, kramdown line_numbers = true,
|
||||
// {% highlight LANG linenos %}...{% endhighlight %}:
|
||||
.highlight .table-wrapper {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
|
||||
td,
|
||||
pre {
|
||||
@include fs-2;
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
background-color: $code-background-color;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
td.gl {
|
||||
padding-right: $sp-3;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin: 0;
|
||||
line-height: 2;
|
||||
}
|
||||
}
|
||||
|
||||
.highlight .c {
|
||||
color: #586e75;
|
||||
} // comment //
|
||||
.highlight .err {
|
||||
color: #93a1a1;
|
||||
} // error //
|
||||
.highlight .g {
|
||||
color: #93a1a1;
|
||||
} // generic //
|
||||
.highlight .k {
|
||||
color: #859900;
|
||||
} // keyword //
|
||||
.highlight .l {
|
||||
color: #93a1a1;
|
||||
} // literal //
|
||||
.highlight .n {
|
||||
color: #93a1a1;
|
||||
} // name //
|
||||
.highlight .o {
|
||||
color: #859900;
|
||||
} // operator //
|
||||
.highlight .x {
|
||||
color: #cb4b16;
|
||||
} // other //
|
||||
.highlight .p {
|
||||
color: #93a1a1;
|
||||
} // punctuation //
|
||||
.highlight .cm {
|
||||
color: #586e75;
|
||||
} // comment.multiline //
|
||||
.highlight .cp {
|
||||
color: #859900;
|
||||
} // comment.preproc //
|
||||
.highlight .c1 {
|
||||
color: #586e75;
|
||||
} // comment.single //
|
||||
.highlight .cs {
|
||||
color: #859900;
|
||||
} // comment.special //
|
||||
.highlight .gd {
|
||||
color: #2aa198;
|
||||
} // generic.deleted //
|
||||
.highlight .ge {
|
||||
font-style: italic;
|
||||
color: #93a1a1;
|
||||
} // generic.emph //
|
||||
.highlight .gr {
|
||||
color: #dc322f;
|
||||
} // generic.error //
|
||||
.highlight .gh {
|
||||
color: #cb4b16;
|
||||
} // generic.heading //
|
||||
.highlight .gi {
|
||||
color: #859900;
|
||||
} // generic.inserted //
|
||||
.highlight .go {
|
||||
color: #93a1a1;
|
||||
} // generic.output //
|
||||
.highlight .gp {
|
||||
color: #93a1a1;
|
||||
} // generic.prompt //
|
||||
.highlight .gs {
|
||||
font-weight: bold;
|
||||
color: #93a1a1;
|
||||
} // generic.strong //
|
||||
.highlight .gu {
|
||||
color: #cb4b16;
|
||||
} // generic.subheading //
|
||||
.highlight .gt {
|
||||
color: #93a1a1;
|
||||
} // generic.traceback //
|
||||
.highlight .kc {
|
||||
color: #cb4b16;
|
||||
} // keyword.constant //
|
||||
.highlight .kd {
|
||||
color: #268bd2;
|
||||
} // keyword.declaration //
|
||||
.highlight .kn {
|
||||
color: #859900;
|
||||
} // keyword.namespace //
|
||||
.highlight .kp {
|
||||
color: #859900;
|
||||
} // keyword.pseudo //
|
||||
.highlight .kr {
|
||||
color: #268bd2;
|
||||
} // keyword.reserved //
|
||||
.highlight .kt {
|
||||
color: #dc322f;
|
||||
} // keyword.type //
|
||||
.highlight .ld {
|
||||
color: #93a1a1;
|
||||
} // literal.date //
|
||||
.highlight .m {
|
||||
color: #2aa198;
|
||||
} // literal.number //
|
||||
.highlight .s {
|
||||
color: #2aa198;
|
||||
} // literal.string //
|
||||
.highlight .na {
|
||||
color: #555;
|
||||
} // name.attribute //
|
||||
.highlight .nb {
|
||||
color: #b58900;
|
||||
} // name.builtin //
|
||||
.highlight .nc {
|
||||
color: #268bd2;
|
||||
} // name.class //
|
||||
.highlight .no {
|
||||
color: #cb4b16;
|
||||
} // name.constant //
|
||||
.highlight .nd {
|
||||
color: #268bd2;
|
||||
} // name.decorator //
|
||||
.highlight .ni {
|
||||
color: #cb4b16;
|
||||
} // name.entity //
|
||||
.highlight .ne {
|
||||
color: #cb4b16;
|
||||
} // name.exception //
|
||||
.highlight .nf {
|
||||
color: #268bd2;
|
||||
} // name.function //
|
||||
.highlight .nl {
|
||||
color: #555;
|
||||
} // name.label //
|
||||
.highlight .nn {
|
||||
color: #93a1a1;
|
||||
} // name.namespace //
|
||||
.highlight .nx {
|
||||
color: #555;
|
||||
} // name.other //
|
||||
.highlight .py {
|
||||
color: #93a1a1;
|
||||
} // name.property //
|
||||
.highlight .nt {
|
||||
color: #268bd2;
|
||||
} // name.tag //
|
||||
.highlight .nv {
|
||||
color: #268bd2;
|
||||
} // name.variable //
|
||||
.highlight .ow {
|
||||
color: #859900;
|
||||
} // operator.word //
|
||||
.highlight .w {
|
||||
color: #93a1a1;
|
||||
} // text.whitespace //
|
||||
.highlight .mf {
|
||||
color: #2aa198;
|
||||
} // literal.number.float //
|
||||
.highlight .mh {
|
||||
color: #2aa198;
|
||||
} // literal.number.hex //
|
||||
.highlight .mi {
|
||||
color: #2aa198;
|
||||
} // literal.number.integer //
|
||||
.highlight .mo {
|
||||
color: #2aa198;
|
||||
} // literal.number.oct //
|
||||
.highlight .sb {
|
||||
color: #586e75;
|
||||
} // literal.string.backtick //
|
||||
.highlight .sc {
|
||||
color: #2aa198;
|
||||
} // literal.string.char //
|
||||
.highlight .sd {
|
||||
color: #93a1a1;
|
||||
} // literal.string.doc //
|
||||
.highlight .s2 {
|
||||
color: #2aa198;
|
||||
} // literal.string.double //
|
||||
.highlight .se {
|
||||
color: #cb4b16;
|
||||
} // literal.string.escape //
|
||||
.highlight .sh {
|
||||
color: #93a1a1;
|
||||
} // literal.string.heredoc //
|
||||
.highlight .si {
|
||||
color: #2aa198;
|
||||
} // literal.string.interpol //
|
||||
.highlight .sx {
|
||||
color: #2aa198;
|
||||
} // literal.string.other //
|
||||
.highlight .sr {
|
||||
color: #dc322f;
|
||||
} // literal.string.regex //
|
||||
.highlight .s1 {
|
||||
color: #2aa198;
|
||||
} // literal.string.single //
|
||||
.highlight .ss {
|
||||
color: #2aa198;
|
||||
} // literal.string.symbol //
|
||||
.highlight .bp {
|
||||
color: #268bd2;
|
||||
} // name.builtin.pseudo //
|
||||
.highlight .vc {
|
||||
color: #268bd2;
|
||||
} // name.variable.class //
|
||||
.highlight .vg {
|
||||
color: #268bd2;
|
||||
} // name.variable.global //
|
||||
.highlight .vi {
|
||||
color: #268bd2;
|
||||
} // name.variable.instance //
|
||||
.highlight .il {
|
||||
color: #2aa198;
|
||||
} // literal.number.integer.long //
|
||||
|
||||
//
|
||||
// Code examples (rendered)
|
||||
//
|
||||
|
||||
.code-example {
|
||||
padding: $sp-3;
|
||||
margin-bottom: $sp-3;
|
||||
overflow: auto;
|
||||
border: 1px solid $border-color;
|
||||
border-radius: $border-radius;
|
||||
|
||||
+ .highlighter-rouge,
|
||||
+ figure.highlight {
|
||||
position: relative;
|
||||
margin-top: -$sp-4;
|
||||
border-right: 1px solid $border-color;
|
||||
border-bottom: 1px solid $border-color;
|
||||
border-left: 1px solid $border-color;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
$body-background-color: $grey-dk-300;
|
||||
$sidebar-color: $grey-dk-300;
|
||||
$border-color: $grey-dk-200;
|
||||
|
||||
$body-text-color: $grey-lt-300;
|
||||
$body-heading-color: $grey-lt-000;
|
||||
$nav-child-link-color: $grey-dk-000;
|
||||
$search-result-preview-color: $grey-dk-000;
|
||||
|
||||
$link-color: $blue-000;
|
||||
$btn-primary-color: $blue-200;
|
||||
$base-button-color: $grey-dk-250;
|
||||
|
||||
$code-background-color: $grey-dk-250;
|
||||
$search-background-color: $grey-dk-250;
|
||||
$table-background-color: $grey-dk-250;
|
||||
$feedback-color: darken($sidebar-color, 3%);
|
@ -1,94 +0,0 @@
|
||||
$blue-000: $color-accent-fg-note-dark;
|
||||
$dark-mode-bg: #202225;
|
||||
|
||||
$body-background-color: $dark-mode-bg;
|
||||
$border-color: $grey-dk-200;
|
||||
|
||||
$body-text-color: $grey-lt-300;
|
||||
$body-heading-color: $grey-lt-000;
|
||||
$nav-child-link-color: $grey-lt-300;
|
||||
$search-result-preview-color: $grey-lt-300;
|
||||
|
||||
$link-color: $green-000;
|
||||
$btn-primary-color: $blue-200;
|
||||
$base-button-color: $grey-dk-250;
|
||||
|
||||
$code-background-color: $grey-dk-250;
|
||||
$search-background-color: $grey-dk-250;
|
||||
$table-background-color: $grey-dk-250;
|
||||
$feedback-color: darken($sidebar-color, 7%);
|
||||
|
||||
.footer-logo a {
|
||||
color: $blue-000;
|
||||
}
|
||||
|
||||
/* .site-footer a {
|
||||
color: $blue-000;
|
||||
} */
|
||||
|
||||
.aux-nav-list a {
|
||||
color: $blue-000;
|
||||
}
|
||||
|
||||
#markdown-toc a {
|
||||
color: $blue-000;
|
||||
}
|
||||
|
||||
p>a {
|
||||
color: $blue-000;
|
||||
}
|
||||
|
||||
p>strong>em>a {
|
||||
color: $blue-000;
|
||||
}
|
||||
|
||||
.breadcrumb-nav-list a {
|
||||
color: $blue-000;
|
||||
}
|
||||
|
||||
ul>li>a {
|
||||
color: $blue-000;
|
||||
}
|
||||
|
||||
#main-content blockquote {
|
||||
background-color: $dark-mode-bg;
|
||||
}
|
||||
|
||||
#main-content blockquote > p > span > small {
|
||||
color: $grey-lt-300;
|
||||
}
|
||||
|
||||
#main-content a {
|
||||
color: $blue-000;
|
||||
}
|
||||
|
||||
.main-header.nav-open {
|
||||
background-color: $dark-mode-bg;
|
||||
}
|
||||
|
||||
.site-footer a {
|
||||
color: #00ffff;
|
||||
text-decoration: none;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.site-footer {
|
||||
color: #00ffff;
|
||||
}
|
||||
|
||||
#main-content .octicon-note {
|
||||
fill: $color-accent-fg-note-dark;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#main-content .icon-span-note {
|
||||
color: $color-accent-fg-note-dark;
|
||||
}
|
||||
|
||||
#main-content .octicon-note>path {
|
||||
fill: $color-accent-fg-note-dark;
|
||||
}
|
||||
|
||||
#main-content .octicon-alert>path {
|
||||
fill: $color-accent-fg-warning;
|
||||
}
|
@ -1,244 +0,0 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
//
|
||||
// Styles for rendered markdown in the .main-content container
|
||||
//
|
||||
// stylelint-disable selector-no-type, max-nesting-depth, selector-max-compound-selectors, selector-max-type
|
||||
|
||||
.main-content {
|
||||
line-height: $content-line-height;
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl,
|
||||
pre,
|
||||
address,
|
||||
blockquote,
|
||||
.table-wrapper {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
a {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
ul,
|
||||
ol {
|
||||
padding-left: 1.5em;
|
||||
}
|
||||
|
||||
li {
|
||||
.highlight {
|
||||
margin-top: $sp-1;
|
||||
}
|
||||
}
|
||||
|
||||
ol {
|
||||
list-style-type: none;
|
||||
counter-reset: step-counter;
|
||||
|
||||
> li {
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: 0.2em;
|
||||
left: -1.6em;
|
||||
color: $grey-dk-000;
|
||||
content: counter(step-counter);
|
||||
counter-increment: step-counter;
|
||||
@include fs-3;
|
||||
|
||||
@include mq(sm) {
|
||||
top: 0.11em;
|
||||
}
|
||||
}
|
||||
|
||||
ol {
|
||||
counter-reset: sub-counter;
|
||||
|
||||
li {
|
||||
&::before {
|
||||
content: counter(sub-counter, lower-alpha);
|
||||
counter-increment: sub-counter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
|
||||
> li {
|
||||
&::before {
|
||||
position: absolute;
|
||||
margin-left: -1.4em;
|
||||
color: $grey-dk-000;
|
||||
content: "•";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.comments-form ul {
|
||||
list-style: none;
|
||||
|
||||
> li {
|
||||
&::before {
|
||||
position: absolute;
|
||||
margin-left: -1.4em;
|
||||
color: $grey-dk-000;
|
||||
content: '' !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.task-list {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.task-list-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
}
|
||||
}
|
||||
|
||||
.task-list-item-checkbox {
|
||||
margin-right: 0.6em;
|
||||
}
|
||||
|
||||
hr + * {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
h1:first-of-type {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
dl {
|
||||
display: grid;
|
||||
grid-template: auto / 10em 1fr;
|
||||
}
|
||||
|
||||
dt,
|
||||
dd {
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
grid-column: 1;
|
||||
font-weight: 500;
|
||||
text-align: right;
|
||||
&::after {
|
||||
content: ":";
|
||||
}
|
||||
}
|
||||
|
||||
dd {
|
||||
grid-column: 2;
|
||||
margin-bottom: 0;
|
||||
margin-left: 1em;
|
||||
blockquote,
|
||||
div,
|
||||
dl,
|
||||
dt,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
li,
|
||||
ol,
|
||||
p,
|
||||
pre,
|
||||
table,
|
||||
ul,
|
||||
.table-wrapper {
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dd,
|
||||
ol,
|
||||
ul {
|
||||
dl:first-child {
|
||||
dt:first-child,
|
||||
dd:nth-child(2) {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.anchor-heading {
|
||||
position: absolute;
|
||||
right: -$sp-4;
|
||||
width: $sp-5;
|
||||
height: 100%;
|
||||
padding-right: $sp-1;
|
||||
padding-left: $sp-1;
|
||||
overflow: visible;
|
||||
|
||||
@include mq(md) {
|
||||
right: auto;
|
||||
left: -$sp-5;
|
||||
}
|
||||
|
||||
svg {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: $link-color;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.anchor-heading:hover,
|
||||
h1:hover > .anchor-heading,
|
||||
h2:hover > .anchor-heading,
|
||||
h3:hover > .anchor-heading,
|
||||
h4:hover > .anchor-heading,
|
||||
h5:hover > .anchor-heading,
|
||||
h6:hover > .anchor-heading {
|
||||
svg {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
summary {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
position: relative;
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 0.25em;
|
||||
|
||||
&:first-child {
|
||||
margin-top: $sp-2;
|
||||
}
|
||||
|
||||
+ table,
|
||||
+ .table-wrapper,
|
||||
+ .code-example,
|
||||
+ .highlighter-rouge {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
+ p {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,561 +0,0 @@
|
||||
.side-bar {
|
||||
background: #c9c7c5;
|
||||
}
|
||||
|
||||
.site-footer a {
|
||||
color: #c9c7c5;
|
||||
text-decoration: none;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.site-footer {
|
||||
color: #c9c7c5;
|
||||
}
|
||||
|
||||
.header-container {
|
||||
border-radius: 0;
|
||||
display: inline-block;
|
||||
margin: 0px;
|
||||
width: 270px;
|
||||
}
|
||||
|
||||
.header-buttons ul li {
|
||||
display: inline-block;
|
||||
/* vertical-align: center; */
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.header-buttons ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
>li {
|
||||
height: fit-content;
|
||||
width: fit-content;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
margin-left: -1.4em;
|
||||
color: $grey-dk-000;
|
||||
content: '' !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-list-item a {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.nav-list .nav-list-item .nav-list-expander {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.nav-list .nav-list-item .nav-list-expander:hover,
|
||||
.nav-list .nav-list-item .nav-list-link:hover {
|
||||
text-decoration: underline;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.nav-list .nav-list-item .nav-list-link.active {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.nav-list-item.active .nav-list-expander,
|
||||
.nav-list .nav-list-item>.nav-list .nav-list-item .nav-list-link,
|
||||
.nav-list-item.active a {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.breadcrumb-nav-list-item {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.breadcrumb-nav-list-item::after {
|
||||
margin-right: 0.1rem;
|
||||
}
|
||||
|
||||
.site-header a,
|
||||
.site-button>.icon {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.side-bar a:hover {
|
||||
background-image: none;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-weight: 400;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
hr {
|
||||
border-top: 1px solid rgb(220, 220, 220);
|
||||
}
|
||||
|
||||
.video-container {
|
||||
position: relative;
|
||||
padding-bottom: 56.25%; //16:9
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.video-container iframe {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
background: #eee;
|
||||
border-left: 4px solid #bbb;
|
||||
padding: 5px 10px;
|
||||
margin: 8px 0 16px 0;
|
||||
}
|
||||
|
||||
blockquote p {
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.main-content a {
|
||||
white-space: normal;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.bpTable td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#bpImage {
|
||||
height: 400px;
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.bp {
|
||||
font-size: 20px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.bp::after {
|
||||
content: '';
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 5px solid transparent;
|
||||
border-right: 5px solid transparent;
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
margin-left: 10px;
|
||||
border-top: 5px solid #007575;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.bp.open::after {
|
||||
content: '';
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 5px solid transparent;
|
||||
border-right: 5px solid transparent;
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
margin-left: 10px;
|
||||
border-bottom: 5px solid #007575;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.bpdata {
|
||||
padding-left: 10px;
|
||||
max-height: 0px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.bpdata.open {
|
||||
max-height: 60px;
|
||||
}
|
||||
|
||||
.main-content dl {
|
||||
grid-template: auto / auto 1fr;
|
||||
}
|
||||
|
||||
.rotation {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.caseImage {
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.nav-list-item.active {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.nav-list-item.active:has() {}
|
||||
|
||||
.nav-list-item.active .nav-list-expander,
|
||||
.nav-list .nav-list-item>.nav-list .nav-list-item .nav-list-link,
|
||||
.nav-list-item.active a {
|
||||
color: #000;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-list .nav-list-item>.nav-list .nav-list-item .nav-list-link::before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
height: 100%;
|
||||
width: 20px;
|
||||
top: 0;
|
||||
border-left: 1px solid #00d1d1;
|
||||
padding: 10px 0;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 1px solid #00d1d1;
|
||||
}
|
||||
|
||||
.nav-list .nav-list-item .nav-list-expander {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nav-list .nav-list-item>.nav-list {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media (min-width: 50rem) {
|
||||
.site-nav {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.site-header a {
|
||||
font-size: 20px !important;
|
||||
}
|
||||
|
||||
.rotation {
|
||||
width: calc(100% / 4);
|
||||
}
|
||||
|
||||
.rotation {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 66.375rem) {
|
||||
.site-header a {
|
||||
font-size: 24px !important;
|
||||
}
|
||||
|
||||
.main-content dl {
|
||||
grid-template: auto / 10em 1fr;
|
||||
}
|
||||
|
||||
.rotation:nth-child(1) {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.rotation:nth-child(2) {
|
||||
width: 140px;
|
||||
}
|
||||
|
||||
.rotation:nth-child(3) {
|
||||
width: 90px;
|
||||
}
|
||||
|
||||
.rotation:nth-child(4) {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.nav-list .nav-list-item>.nav-list .nav-list-item .nav-list-link::before {
|
||||
left: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 31.25rem) {
|
||||
h2 {
|
||||
font-size: 28px !important;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 22px !important;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 18px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Alert Styles */
|
||||
|
||||
.alert-warning {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
div.alert code,
|
||||
h2 code {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
/* without this, the links in these notes aren't visible.*/
|
||||
.alert a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.octicon-note {
|
||||
fill: $color-accent-fg-note-light;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.octicon-alert {
|
||||
fill: $color-accent-fg-warning;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.octicon-danger {
|
||||
fill: $color-accent-fg-danger;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.octicon-success {
|
||||
fill: $color-accent-fg-success;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.octicon-tip {
|
||||
fill: $color-accent-fg-tip;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.icon-span-note {
|
||||
color: $color-accent-fg-note-light;
|
||||
}
|
||||
|
||||
.icon-span-warning {
|
||||
color: $color-accent-fg-warning;
|
||||
}
|
||||
|
||||
.icon-span-success {
|
||||
color: $color-accent-fg-success;
|
||||
}
|
||||
|
||||
.icon-span-tip {
|
||||
color: $color-accent-fg-tip;
|
||||
}
|
||||
|
||||
.icon-span-danger {
|
||||
color: $color-accent-fg-tip;
|
||||
}
|
||||
|
||||
|
||||
.bs-example {
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.bs-callout {
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
border: 1px solid #eee;
|
||||
border-left-width: 5px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.bs-callout h4 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.bs-callout p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.bs-callout code {
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.bs-callout+.bs-callout {
|
||||
margin-top: -5px;
|
||||
}
|
||||
|
||||
.bs-callout-default {
|
||||
border-left-color: #777;
|
||||
}
|
||||
|
||||
.bs-callout-default h4 {
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.bs-callout-primary {
|
||||
border-left-color: #428bca;
|
||||
}
|
||||
|
||||
.bs-callout-primary h4 {
|
||||
color: #428bca;
|
||||
}
|
||||
|
||||
.bs-callout-success {
|
||||
border-left-color: #5cb85c;
|
||||
}
|
||||
|
||||
.bs-callout-success h4 {
|
||||
color: #5cb85c;
|
||||
}
|
||||
|
||||
.bs-callout-danger {
|
||||
border-left-color: #d9534f;
|
||||
}
|
||||
|
||||
.bs-callout-danger h4 {
|
||||
color: #d9534f;
|
||||
}
|
||||
|
||||
.bs-callout-warning {
|
||||
border-left-color: #f0ad4e;
|
||||
}
|
||||
|
||||
.bs-callout-warning h4 {
|
||||
color: #f0ad4e;
|
||||
}
|
||||
|
||||
.bs-callout-info {
|
||||
border-left-color: #5bc0de;
|
||||
}
|
||||
|
||||
.bs-callout-info h4 {
|
||||
color: #5bc0de;
|
||||
}
|
||||
|
||||
/* FAQ page */
|
||||
#accordion .panel-heading {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
a.accordion-toggle,
|
||||
a.accordion-collapsed {
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/*
|
||||
* Let's target IE to respect aspect ratios and sizes for img tags containing SVG files
|
||||
*
|
||||
* [1] IE9
|
||||
* [2] IE10+
|
||||
*/
|
||||
/* 1 */
|
||||
.ie9 img[src$=".svg"] {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* 2 */
|
||||
@media screen and (-ms-high-contrast: active),
|
||||
(-ms-high-contrast: none) {
|
||||
img[src$=".svg"] {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 900px),
|
||||
only screen and (min-device-width: 900px) {
|
||||
.col-md-9 img {
|
||||
max-width: 700px;
|
||||
max-height: 700px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Font Awesome */
|
||||
|
||||
a.fa.fa-envelope-o.mailto {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* this part adds an icon after external links, using FontAwesome*/
|
||||
/* a[href^="http://"]:after,
|
||||
a[href^="https://"]:after {
|
||||
content: "\f08e";
|
||||
font-family: FontAwesome;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
padding-left: 3px;
|
||||
} */
|
||||
|
||||
/* Strip the outbound icon when this class is present */
|
||||
/* a[href].noCrossRef::after,
|
||||
a.no_icon:after {
|
||||
content: "" !important;
|
||||
padding-left: 0;
|
||||
} */
|
||||
|
||||
/* Custom Checkboxes */
|
||||
input[type=checkbox] {
|
||||
cursor: pointer;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin: 10px;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
-o-appearance: none;
|
||||
appearance: none;
|
||||
outline: 1px solid lightblue;
|
||||
box-shadow: rgba(0, 0, 0, 0.25) 0px 54px 55px, rgba(0, 0, 0, 0.12) 0px -12px 30px, rgba(0, 0, 0, 0.12) 0px 4px 6px, rgba(0, 0, 0, 0.17) 0px 12px 13px, rgba(0, 0, 0, 0.09) 0px -3px 5px;
|
||||
background-clip: content-box;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
input,
|
||||
input:focus {
|
||||
border: none;
|
||||
border-radius: 2pt;
|
||||
box-shadow: 0 0 0 1pt grey;
|
||||
outline: none;
|
||||
transition: .1s;
|
||||
}
|
||||
|
||||
input[type=checkbox]:checked {
|
||||
background-color: #3899ff;
|
||||
|
||||
}
|
||||
|
||||
input[type=checkbox]:focus {
|
||||
box-shadow: 0 0 3pt 2pt cornflowerblue;
|
||||
}
|
||||
|
||||
#main-content .task-list-item-checkbox {}
|
||||
|
||||
body {
|
||||
cursor: default
|
||||
}
|
||||
|
||||
/* width */
|
||||
::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
/* Track */
|
||||
::-webkit-scrollbar-track {
|
||||
box-shadow: inset 0 0 5px grey;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
/* Handle */
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #6d7faeb4;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
/* Handle on hover */
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #6d7fae;
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
//
|
||||
// Labels (not the form kind)
|
||||
//
|
||||
|
||||
.label,
|
||||
.label-blue {
|
||||
display: inline-block;
|
||||
padding-top: 0.16em;
|
||||
padding-right: 0.56em;
|
||||
padding-bottom: 0.16em;
|
||||
padding-left: 0.56em;
|
||||
margin-right: $sp-2;
|
||||
margin-left: $sp-2;
|
||||
color: $white;
|
||||
text-transform: uppercase;
|
||||
vertical-align: middle;
|
||||
background-color: $blue-100;
|
||||
@include fs-2;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.label-green {
|
||||
background-color: $green-200;
|
||||
}
|
||||
|
||||
.label-purple {
|
||||
background-color: $purple-100;
|
||||
}
|
||||
|
||||
.label-red {
|
||||
background-color: $red-200;
|
||||
}
|
||||
|
||||
.label-yellow {
|
||||
color: $grey-dk-200;
|
||||
background-color: $yellow-200;
|
||||
}
|
@ -1,205 +0,0 @@
|
||||
//
|
||||
// The basic two column layout
|
||||
//
|
||||
|
||||
.side-bar {
|
||||
z-index: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
background-color: $sidebar-color;
|
||||
|
||||
@include mq(md) {
|
||||
flex-wrap: nowrap;
|
||||
position: fixed;
|
||||
width: $nav-width-md;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
border-right: $border $border-color;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
@include mq(lg) {
|
||||
width: calc((100% - #{$nav-width + $content-width}) / 2 + #{$nav-width});
|
||||
min-width: $nav-width;
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
@include mq(md) {
|
||||
position: relative;
|
||||
max-width: $content-width;
|
||||
margin-left: $nav-width-md;
|
||||
}
|
||||
|
||||
@include mq(lg) {
|
||||
margin-left: calc(
|
||||
(100% - #{$nav-width + $content-width}) / 2 + #{$nav-width}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
.main-content-wrap {
|
||||
@include container;
|
||||
padding-top: $gutter-spacing-sm;
|
||||
padding-bottom: $gutter-spacing-sm;
|
||||
|
||||
@include mq(md) {
|
||||
padding-top: $gutter-spacing;
|
||||
padding-bottom: $gutter-spacing;
|
||||
}
|
||||
}
|
||||
|
||||
.main-header {
|
||||
z-index: 0;
|
||||
display: none;
|
||||
background-color: $sidebar-color;
|
||||
|
||||
@include mq(md) {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
height: $header-height;
|
||||
background-color: $body-background-color;
|
||||
border-bottom: $border $border-color;
|
||||
}
|
||||
|
||||
&.nav-open {
|
||||
display: block;
|
||||
|
||||
@include mq(md) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.site-nav,
|
||||
.site-header,
|
||||
.site-footer {
|
||||
width: 100%;
|
||||
|
||||
@include mq(lg) {
|
||||
width: $nav-width;
|
||||
}
|
||||
}
|
||||
|
||||
.site-nav {
|
||||
display: none;
|
||||
|
||||
&.nav-open {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@include mq(md) {
|
||||
display: block;
|
||||
padding-top: $sp-8;
|
||||
padding-bottom: $gutter-spacing-sm;
|
||||
overflow-y: auto;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.site-header {
|
||||
display: flex;
|
||||
min-height: $header-height;
|
||||
align-items: center;
|
||||
|
||||
@include mq(md) {
|
||||
height: $header-height;
|
||||
max-height: $header-height;
|
||||
border-bottom: $border $border-color;
|
||||
}
|
||||
}
|
||||
|
||||
.site-title {
|
||||
@include container;
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
padding-top: $sp-3;
|
||||
padding-bottom: $sp-3;
|
||||
color: $body-heading-color;
|
||||
@include fs-6;
|
||||
|
||||
@include mq(md) {
|
||||
padding-top: $sp-2;
|
||||
padding-bottom: $sp-2;
|
||||
}
|
||||
}
|
||||
|
||||
@if variable-exists(logo) {
|
||||
.site-logo {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url($logo);
|
||||
background-repeat: no-repeat;
|
||||
background-position: left center;
|
||||
background-size: contain;
|
||||
}
|
||||
}
|
||||
|
||||
.site-button {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
padding: $gutter-spacing-sm;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@include mq(md) {
|
||||
.site-header .site-button {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.site-title:hover {
|
||||
background-image: linear-gradient(
|
||||
-90deg,
|
||||
rgba($feedback-color, 1) 0%,
|
||||
rgba($feedback-color, 0.8) 80%,
|
||||
rgba($feedback-color, 0) 100%
|
||||
);
|
||||
}
|
||||
|
||||
.site-button:hover {
|
||||
background-image: linear-gradient(
|
||||
-90deg,
|
||||
rgba($feedback-color, 1) 0%,
|
||||
rgba($feedback-color, 0.8) 100%
|
||||
);
|
||||
}
|
||||
|
||||
// stylelint-disable selector-max-type
|
||||
|
||||
body {
|
||||
position: relative;
|
||||
padding-bottom: $sp-10;
|
||||
overflow-y: scroll;
|
||||
|
||||
@include mq(md) {
|
||||
position: static;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// stylelint-enable selector-max-type
|
||||
|
||||
.site-footer {
|
||||
@include container;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding-top: $sp-4;
|
||||
padding-bottom: $sp-4;
|
||||
color: $grey-dk-000;
|
||||
@include fs-2;
|
||||
|
||||
@include mq(md) {
|
||||
position: static;
|
||||
justify-self: end;
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: $sp-5;
|
||||
height: $sp-5;
|
||||
color: $link-color;
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
//
|
||||
// Import external dependencies
|
||||
//
|
||||
@import "./vendor/normalize.scss/normalize.scss";
|
||||
|
||||
//
|
||||
// Modules
|
||||
//
|
||||
@import "./base";
|
||||
@import "./layout";
|
||||
@import "./content";
|
||||
@import "./navigation";
|
||||
@import "./typography";
|
||||
@import "./labels";
|
||||
@import "./buttons";
|
||||
@import "./search";
|
||||
@import "./tables";
|
||||
@import "./code";
|
||||
@import "./utilities/utilities";
|
||||
@import "./print";
|
@ -1,219 +0,0 @@
|
||||
//
|
||||
// Main nav, breadcrumb, etc...
|
||||
//
|
||||
// stylelint-disable selector-no-type, max-nesting-depth, selector-max-compound-selectors, selector-max-type, selector-max-specificity
|
||||
|
||||
.nav-list {
|
||||
padding: 0;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
list-style: none;
|
||||
|
||||
.nav-list-item {
|
||||
@include fs-4;
|
||||
position: relative;
|
||||
margin: 0;
|
||||
|
||||
@include mq(md) {
|
||||
@include fs-3;
|
||||
}
|
||||
|
||||
.nav-list-link {
|
||||
display: block;
|
||||
min-height: $nav-list-item-height-sm;
|
||||
padding-top: $sp-1;
|
||||
padding-bottom: $sp-1;
|
||||
line-height: #{$nav-list-item-height-sm - 2 * $sp-1};
|
||||
@if $nav-list-expander-right {
|
||||
padding-right: $nav-list-item-height-sm;
|
||||
padding-left: $gutter-spacing-sm;
|
||||
} @else {
|
||||
padding-right: $gutter-spacing-sm;
|
||||
padding-left: $nav-list-item-height-sm;
|
||||
}
|
||||
|
||||
@include mq(md) {
|
||||
min-height: $nav-list-item-height;
|
||||
line-height: #{$nav-list-item-height - 2 * $sp-1};
|
||||
@if $nav-list-expander-right {
|
||||
padding-right: $nav-list-item-height;
|
||||
padding-left: $gutter-spacing;
|
||||
} @else {
|
||||
padding-right: $gutter-spacing;
|
||||
padding-left: $nav-list-item-height;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
background-image: linear-gradient(
|
||||
-90deg,
|
||||
rgba($feedback-color, 1) 0%,
|
||||
rgba($feedback-color, 0.8) 80%,
|
||||
rgba($feedback-color, 0) 100%
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
.nav-list-expander {
|
||||
position: absolute;
|
||||
@if $nav-list-expander-right {
|
||||
right: 0;
|
||||
}
|
||||
width: $nav-list-item-height-sm;
|
||||
height: $nav-list-item-height-sm;
|
||||
padding-top: #{$nav-list-item-height-sm / 4};
|
||||
padding-right: #{$nav-list-item-height-sm / 4};
|
||||
padding-bottom: #{$nav-list-item-height-sm / 4};
|
||||
padding-left: #{$nav-list-item-height-sm / 4};
|
||||
color: $link-color;
|
||||
|
||||
@include mq(md) {
|
||||
width: $nav-list-item-height;
|
||||
height: $nav-list-item-height;
|
||||
padding-top: #{$nav-list-item-height / 4};
|
||||
padding-right: #{$nav-list-item-height / 4};
|
||||
padding-bottom: #{$nav-list-item-height / 4};
|
||||
padding-left: #{$nav-list-item-height / 4};
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-image: linear-gradient(
|
||||
-90deg,
|
||||
rgba($feedback-color, 1) 0%,
|
||||
rgba($feedback-color, 0.8) 100%
|
||||
);
|
||||
}
|
||||
|
||||
@if $nav-list-expander-right {
|
||||
svg {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .nav-list {
|
||||
display: none;
|
||||
padding-left: $sp-3;
|
||||
list-style: none;
|
||||
|
||||
.nav-list-item {
|
||||
position: relative;
|
||||
|
||||
.nav-list-link {
|
||||
color: $nav-child-link-color;
|
||||
}
|
||||
|
||||
.nav-list-expander {
|
||||
color: $nav-child-link-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
> .nav-list-expander svg {
|
||||
@if $nav-list-expander-right {
|
||||
transform: rotate(-90deg);
|
||||
} @else {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
> .nav-list {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-category {
|
||||
padding-top: $sp-2;
|
||||
padding-right: $gutter-spacing-sm;
|
||||
padding-bottom: $sp-2;
|
||||
padding-left: $gutter-spacing-sm;
|
||||
font-weight: 600;
|
||||
text-align: end;
|
||||
text-transform: uppercase;
|
||||
border-bottom: $border $border-color;
|
||||
@include fs-2;
|
||||
|
||||
@include mq(md) {
|
||||
padding-right: $gutter-spacing;
|
||||
padding-left: $gutter-spacing;
|
||||
margin-top: $gutter-spacing-sm;
|
||||
text-align: start;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Aux nav
|
||||
|
||||
.aux-nav {
|
||||
height: 100%;
|
||||
overflow-x: auto;
|
||||
@include fs-2;
|
||||
|
||||
.aux-nav-list {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.aux-nav-list-item {
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@include mq(md) {
|
||||
padding-right: $gutter-spacing-sm;
|
||||
}
|
||||
}
|
||||
|
||||
// Breadcrumb nav
|
||||
|
||||
.breadcrumb-nav {
|
||||
@include mq(md) {
|
||||
margin-top: -$sp-4;
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumb-nav-list {
|
||||
padding-left: 0;
|
||||
margin-bottom: $sp-3;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.breadcrumb-nav-list-item {
|
||||
display: table-cell;
|
||||
@include fs-2;
|
||||
|
||||
&::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&::after {
|
||||
display: inline-block;
|
||||
margin-right: $sp-2;
|
||||
margin-left: $sp-2;
|
||||
color: $grey-dk-000;
|
||||
content: "/";
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
&::after {
|
||||
content: "";
|
||||
}
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
// stylelint-disable selector-max-specificity, selector-max-id, selector-max-type, selector-no-qualifying-type, primer/no-override,
|
||||
|
||||
@media print {
|
||||
.site-footer,
|
||||
.site-button,
|
||||
#edit-this-page,
|
||||
#back-to-top,
|
||||
.site-nav,
|
||||
.main-header {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.side-bar {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
border-right: 0 !important;
|
||||
}
|
||||
|
||||
.site-header {
|
||||
border-bottom: 1px solid $border-color;
|
||||
}
|
||||
|
||||
.site-title {
|
||||
font-size: $root-font-size !important;
|
||||
font-weight: 700 !important;
|
||||
}
|
||||
|
||||
.text-small {
|
||||
font-size: 8pt !important;
|
||||
}
|
||||
|
||||
pre.highlight {
|
||||
border: 1px solid $border-color;
|
||||
}
|
||||
|
||||
.main {
|
||||
max-width: none;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
@ -1,323 +0,0 @@
|
||||
//
|
||||
// Search input and autocomplete
|
||||
//
|
||||
|
||||
.search {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
flex-grow: 1;
|
||||
height: $sp-10;
|
||||
padding: $sp-2;
|
||||
transition: padding linear #{$transition-duration / 2};
|
||||
|
||||
@include mq(md) {
|
||||
position: relative !important;
|
||||
width: auto !important;
|
||||
height: 100% !important;
|
||||
padding: 0;
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
.search-input-wrap {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
height: $sp-8;
|
||||
overflow: hidden;
|
||||
border-radius: $border-radius;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12), 0 3px 10px rgba(0, 0, 0, 0.08);
|
||||
transition: height linear #{$transition-duration / 2};
|
||||
|
||||
@include mq(md) {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
max-width: $search-results-width;
|
||||
height: 100% !important;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
transition: width ease $transition-duration;
|
||||
}
|
||||
}
|
||||
|
||||
.search-input {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding-top: $sp-2;
|
||||
padding-right: $gutter-spacing-sm;
|
||||
padding-bottom: $sp-2;
|
||||
padding-left: #{$gutter-spacing-sm + $sp-5};
|
||||
font-size: 16px;
|
||||
background-color: $search-background-color;
|
||||
border-top: 0;
|
||||
border-right: 0;
|
||||
border-bottom: 0;
|
||||
border-left: 0;
|
||||
border-radius: 0;
|
||||
|
||||
@include mq(md) {
|
||||
padding-top: $gutter-spacing-sm;
|
||||
padding-bottom: $gutter-spacing-sm;
|
||||
padding-left: #{$gutter-spacing + $sp-5};
|
||||
font-size: 14px;
|
||||
background-color: $body-background-color;
|
||||
transition: padding-left linear #{$transition-duration / 2};
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
|
||||
+ .search-label .search-icon {
|
||||
color: $link-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-label {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
padding-left: $gutter-spacing-sm;
|
||||
|
||||
@include mq(md) {
|
||||
padding-left: $gutter-spacing;
|
||||
transition: padding-left linear #{$transition-duration / 2};
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
width: #{$sp-4 * 1.2};
|
||||
height: #{$sp-4 * 1.2};
|
||||
align-self: center;
|
||||
color: $grey-dk-000;
|
||||
}
|
||||
}
|
||||
|
||||
.search-results {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
display: none;
|
||||
width: 100%;
|
||||
max-height: calc(100% - #{$sp-10});
|
||||
overflow-y: auto;
|
||||
background-color: $search-background-color;
|
||||
border-bottom-right-radius: $border-radius;
|
||||
border-bottom-left-radius: $border-radius;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12), 0 3px 10px rgba(0, 0, 0, 0.08);
|
||||
|
||||
@include mq(md) {
|
||||
top: 100%;
|
||||
width: $search-results-width;
|
||||
max-height: calc(100vh - 200%) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.search-results-list {
|
||||
padding-left: 0;
|
||||
margin-bottom: $sp-1;
|
||||
list-style: none;
|
||||
@include fs-4;
|
||||
|
||||
@include mq(md) {
|
||||
@include fs-3;
|
||||
}
|
||||
}
|
||||
|
||||
.search-results-list-item {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.search-result {
|
||||
display: block;
|
||||
padding-top: $sp-1;
|
||||
padding-right: $sp-3;
|
||||
padding-bottom: $sp-1;
|
||||
padding-left: $sp-3;
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
background-color: $feedback-color;
|
||||
}
|
||||
}
|
||||
|
||||
.search-result-title {
|
||||
display: block;
|
||||
padding-top: $sp-2;
|
||||
padding-bottom: $sp-2;
|
||||
|
||||
@include mq(sm) {
|
||||
display: inline-block;
|
||||
width: 40%;
|
||||
padding-right: $sp-2;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
|
||||
.search-result-doc {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
word-wrap: break-word;
|
||||
|
||||
&.search-result-doc-parent {
|
||||
opacity: 0.5;
|
||||
@include fs-3;
|
||||
|
||||
@include mq(md) {
|
||||
@include fs-2;
|
||||
}
|
||||
}
|
||||
|
||||
.search-result-icon {
|
||||
width: $sp-4;
|
||||
height: $sp-4;
|
||||
margin-right: $sp-2;
|
||||
color: $link-color;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.search-result-doc-title {
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.search-result-section {
|
||||
margin-left: #{$sp-4 + $sp-2};
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.search-result-rel-url {
|
||||
display: block;
|
||||
margin-left: #{$sp-4 + $sp-2};
|
||||
overflow: hidden;
|
||||
color: $search-result-preview-color;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
@include fs-1;
|
||||
}
|
||||
|
||||
.search-result-previews {
|
||||
display: block;
|
||||
padding-top: $sp-2;
|
||||
padding-bottom: $sp-2;
|
||||
padding-left: $sp-4;
|
||||
margin-left: $sp-2;
|
||||
color: $search-result-preview-color;
|
||||
word-wrap: break-word;
|
||||
border-left: $border;
|
||||
border-left-color: $border-color;
|
||||
@include fs-2;
|
||||
|
||||
@include mq(sm) {
|
||||
display: inline-block;
|
||||
width: 60%;
|
||||
padding-left: $sp-2;
|
||||
margin-left: 0;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
|
||||
.search-result-preview + .search-result-preview {
|
||||
margin-top: $sp-1;
|
||||
}
|
||||
|
||||
.search-result-highlight {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.search-no-result {
|
||||
padding-top: $sp-2;
|
||||
padding-right: $sp-3;
|
||||
padding-bottom: $sp-2;
|
||||
padding-left: $sp-3;
|
||||
@include fs-3;
|
||||
}
|
||||
|
||||
.search-button {
|
||||
position: fixed;
|
||||
right: $sp-4;
|
||||
bottom: $sp-4;
|
||||
display: flex;
|
||||
width: $sp-9;
|
||||
height: $sp-9;
|
||||
background-color: $search-background-color;
|
||||
border: 1px solid rgba($link-color, 0.3);
|
||||
border-radius: #{$sp-9 / 2};
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12), 0 3px 10px rgba(0, 0, 0, 0.08);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.search-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
width: 0;
|
||||
height: 0;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
opacity: 0;
|
||||
transition: opacity ease $transition-duration, width 0s $transition-duration,
|
||||
height 0s $transition-duration;
|
||||
}
|
||||
|
||||
.search-active {
|
||||
.search {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.search-input-wrap {
|
||||
height: $sp-10;
|
||||
border-radius: 0;
|
||||
|
||||
@include mq(md) {
|
||||
width: $search-results-width;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12), 0 3px 10px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
}
|
||||
|
||||
.search-input {
|
||||
background-color: $search-background-color;
|
||||
|
||||
@include mq(md) {
|
||||
padding-left: 2.3rem;
|
||||
}
|
||||
}
|
||||
|
||||
.search-label {
|
||||
@include mq(md) {
|
||||
padding-left: 0.6rem;
|
||||
}
|
||||
}
|
||||
|
||||
.search-results {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.search-overlay {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 1;
|
||||
transition: opacity ease $transition-duration, width 0s, height 0s;
|
||||
}
|
||||
|
||||
@include mq(md) {
|
||||
.main {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.main-header {
|
||||
padding-top: $sp-10;
|
||||
|
||||
@include mq(md) {
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
@function rem($size, $unit: "") {
|
||||
$remSize: $size / $root-font-size;
|
||||
|
||||
@if ($unit == false) {
|
||||
@return #{$remSize};
|
||||
} @else {
|
||||
@return #{$remSize}rem;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user