Initial Commit
16
.github/dependabot.yml
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: npm
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 10
|
||||
commit-message:
|
||||
prefix: chore
|
||||
include: scope
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
commit-message:
|
||||
prefix: ci
|
29
.github/workflows/gh-pages.yml
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
name: Deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy to GitHub Pages
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16.x
|
||||
cache: 'yarn'
|
||||
- name: Install dependencies
|
||||
run: yarn install
|
||||
- name: Build
|
||||
run: yarn docs:build
|
||||
- name: Deploy
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./docs/.vuepress/dist
|
5
.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
/node_modules
|
||||
/docs/.vuepress/dist
|
||||
/.vscode/settings.json
|
||||
*.log
|
||||
.idea
|
10
.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"syler.sass-indented",
|
||||
"alan.stylus",
|
||||
"gruntfuggly.todo-tree",
|
||||
"octref.vetur",
|
||||
"gamunu.vscode-yarn",
|
||||
"editorconfig.editorconfig"
|
||||
]
|
||||
}
|
15
LICENSE
Normal file
|
@ -0,0 +1,15 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2022 LBRY Inc.
|
||||
|
||||
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 OF OTHER DEALINGS IN THE SOFTWARE.
|
16
README.md
Normal file
|
@ -0,0 +1,16 @@
|
|||
# lbry.org
|
||||
The new website for the LBRY Foundation using Vuepress
|
||||
|
||||
## Contributing
|
||||
Learn more about [VuePress](https://vuepress.vuejs.org/) when contributing. New pages should be in the format of `/page/README.md`.
|
||||
|
||||
## Development
|
||||
Install [Node.JS](https://nodejs.org/) v16 or higher (use [nvm](https://github.com/nvm-sh/nvm/blob/master/README.md)) and clone this repository.
|
||||
```sh
|
||||
npm i -g yarn
|
||||
yarn install
|
||||
yarn docs:dev # serves at localhost:8080
|
||||
```
|
||||
|
||||
## License
|
||||
This project is MIT licensed. For the full license, see [LICENSE](LICENSE).
|
13
TODO.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
# TODO
|
||||
|
||||
- [ ] Finish home page
|
||||
- [x] Privacy Policy
|
||||
- [ ] Branding page
|
||||
- [ ] Swarm page
|
||||
- [ ] Chat page (?)
|
||||
- [ ] Roadmap page
|
||||
- [ ] Verified page
|
||||
- [ ] Governance page
|
||||
- [ ] Projects page
|
||||
- [x] 404 page
|
||||
- [ ] Fix grammatical/format errors in the Privacy Policy
|
16
docs/.vuepress/components/IconifyIcon.vue
Normal file
|
@ -0,0 +1,16 @@
|
|||
<template>
|
||||
<Icon :icon="icon" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Icon, addCollection } from '@iconify/vue2'
|
||||
import faSolidIcons from '@iconify/json/json/fa-solid.json';
|
||||
addCollection(faSolidIcons);
|
||||
import faBrandsIcons from '@iconify/json/json/fa-brands.json';
|
||||
addCollection(faBrandsIcons);
|
||||
export default {
|
||||
name: 'IconifyIcon',
|
||||
props: ['icon'],
|
||||
components: { Icon }
|
||||
};
|
||||
</script>
|
27
docs/.vuepress/components/MarkdownImage.vue
Normal file
|
@ -0,0 +1,27 @@
|
|||
<template>
|
||||
<img :src="src" :data-original="original" class="md-img" />
|
||||
</template>
|
||||
|
||||
<style lang="stylus">
|
||||
.md-img
|
||||
margin .5em 10%
|
||||
width 80%
|
||||
border-radius 10px
|
||||
filter drop-shadow(2px 2px 4px rgba(0, 0, 0, 0.25))
|
||||
transition border-radius .2s ease, filter .2s ease
|
||||
// Zoomed in
|
||||
&[style*="z-index"]
|
||||
filter drop-shadow(0px 0px 0px rgba(0, 0, 0, 0.25))
|
||||
border-radius 5px
|
||||
@media (max-width: $MQMobile)
|
||||
.md-img
|
||||
width 100%
|
||||
margin .5em 0
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'markdownimage',
|
||||
props: ['src', 'original'],
|
||||
};
|
||||
</script>
|
55
docs/.vuepress/components/Person.vue
Normal file
|
@ -0,0 +1,55 @@
|
|||
<template>
|
||||
<div class="person">
|
||||
<img
|
||||
v-if="!!avatar" no-zoom
|
||||
draggable="false"
|
||||
:alt="`${name}'s Avatar`"
|
||||
:src="avatar"
|
||||
:class="imageClass ? `image-title ${imageClass}` : 'image-title'">
|
||||
<div class="person-content">
|
||||
<h4 :class="avatar || subtitle ? 'title' : 'title minimal'">{{ name }}</h4>
|
||||
<p v-if="!!subtitle" class="subtitle">{{ subtitle }}</p>
|
||||
<div class="buttons"><slot/></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="stylus">
|
||||
.person
|
||||
border-radius .5em
|
||||
background-color var(--secondaryBG)
|
||||
padding .5em 1em
|
||||
margin .5em
|
||||
display flex
|
||||
.title
|
||||
font-size 24px
|
||||
&.minimal
|
||||
font-size 16px
|
||||
font-weight normal
|
||||
.title, .subtitle
|
||||
margin 0
|
||||
img
|
||||
height 5em
|
||||
& + .person-content
|
||||
margin-left 1em
|
||||
&.large
|
||||
height 10em
|
||||
&.rounded
|
||||
border-radius 50%
|
||||
.person-content
|
||||
display flex
|
||||
flex-direction column
|
||||
flex auto
|
||||
justify-content center
|
||||
.subtitle
|
||||
color var(--tertiaryText)
|
||||
.buttons a
|
||||
line-height 2
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'person',
|
||||
props: ['avatar', 'name', 'subtitle', 'imageClass'],
|
||||
};
|
||||
</script>
|
155
docs/.vuepress/config.js
Normal file
|
@ -0,0 +1,155 @@
|
|||
const sidebar = require('./sidebar.js');
|
||||
|
||||
const metaTitle = 'LBRY Foundation',
|
||||
metaDesc = 'LBRY is a secure, open, and community-run digital marketplace.',
|
||||
metaURL = 'https://lbry.org',
|
||||
metaLogo = '/logo.png',
|
||||
metaColor = '#27E4EB';
|
||||
|
||||
const config = {
|
||||
title: metaTitle,
|
||||
description: metaDesc,
|
||||
main: 'layouts/Layout.vue',
|
||||
head: [
|
||||
// Manifest
|
||||
['link', { rel: 'icon', href: metaLogo }],
|
||||
['link', { rel: 'manifest', href: '/manifest.json' }],
|
||||
['meta', { name: 'viewport', content: 'width=device-width, initial-scale=1' }],
|
||||
|
||||
// Icons
|
||||
['link', { rel: 'mask-icon', href: '/logo/safari-pinned-tab.svg', color: metaColor }],
|
||||
['link', { rel: 'apple-touch-icon', sizes: '180x180', href: '/logo/apple-touch-icon.png' }],
|
||||
['link', { rel: 'icon', type: 'image/svg+xml', href: '/logo.svg' }],
|
||||
['link', { rel: 'icon', sizes: '16x16', href: '/logo/favicon-16x16.png' }],
|
||||
['link', { rel: 'icon', sizes: '32x32', href: '/logo/favicon-32x32.png' }],
|
||||
['link', { rel: 'icon', sizes: '192x192', href: '/logo/android-chrome-192x192.png' }],
|
||||
['link', { rel: 'icon', sizes: '512x512', href: '/logo/android-chrome-512x512.png' }],
|
||||
|
||||
// Theme Color
|
||||
['meta', { name: 'theme-color', content: metaColor }],
|
||||
['meta', { name: 'msapplication-TileColor', content: metaColor }],
|
||||
|
||||
// Twitter
|
||||
['meta', { name: 'twitter:card', content: 'summary' }],
|
||||
['meta', { name: 'twitter:url', content: metaURL }],
|
||||
['meta', { name: 'twitter:title', content: metaTitle }],
|
||||
['meta', { name: 'twitter:description', content: metaDesc }],
|
||||
['meta', { name: 'twitter:image', content: metaLogo }],
|
||||
|
||||
// OpenGraph
|
||||
['meta', { name: 'og:type', content: 'website' }],
|
||||
['meta', { name: 'og:url', content: metaURL }],
|
||||
['meta', { name: 'og:title', content: metaTitle }],
|
||||
['meta', { name: 'og:description', content: metaDesc }],
|
||||
['meta', { name: 'og:locale', content: 'en_US' }],
|
||||
['meta', { name: 'og:image', content: metaLogo }],
|
||||
['meta', {
|
||||
name: 'og:keywords',
|
||||
content: [
|
||||
'lbry'
|
||||
].join(',')
|
||||
}]
|
||||
],
|
||||
plugins: [
|
||||
[
|
||||
'zooming',
|
||||
{
|
||||
selector: '.md-img,img[zoomable]',
|
||||
options: {
|
||||
bgColor: 'black',
|
||||
bgOpacity: 0.5,
|
||||
scaleBase: 0.8
|
||||
}
|
||||
}
|
||||
],
|
||||
'@vuepress/pwa',
|
||||
'@vuepress/last-updated',
|
||||
[
|
||||
'sitemap',
|
||||
{
|
||||
hostname: 'https://lbry.org'
|
||||
}
|
||||
],
|
||||
[
|
||||
require('./plugins/redirect.js'),
|
||||
[
|
||||
// TODO update redirects
|
||||
{ url: 'https://github.com/LBRYFoundation',
|
||||
aliases: ['/github/'] }
|
||||
]
|
||||
],
|
||||
require('./plugins/richmeta.js')
|
||||
],
|
||||
themeConfig: {
|
||||
search: false,
|
||||
nav: [
|
||||
// TODO update?
|
||||
{ text: 'Swarm', link: '/swarm/' },
|
||||
{ text: 'Chat', link: '/chat/' },
|
||||
{ text: 'Roadmap', link: '/roadmap/' },
|
||||
{ text: 'Verified', link: '/verified/' },
|
||||
{ text: 'Governance', link: '/governance/' },
|
||||
{ text: 'Projects', link: '/projects/' }
|
||||
],
|
||||
sidebar,
|
||||
nextLinks: true,
|
||||
prevlinks: true,
|
||||
docsRepo: 'LBRYFoundation/lbry.org',
|
||||
docsDir: 'docs',
|
||||
editLinks: true,
|
||||
editLinkText: 'Improve this page on GitHub!',
|
||||
logo: '/logo-horizontal.svg',
|
||||
smoothScroll: true,
|
||||
footer: {
|
||||
logo: '/logo-vertical.svg',
|
||||
columns: [
|
||||
{
|
||||
title: 'More',
|
||||
rows: [{
|
||||
text: 'Privacy Policy',
|
||||
link: '/privacy/'
|
||||
},
|
||||
{
|
||||
text: 'Branding',
|
||||
link: '/branding/'
|
||||
},
|
||||
{
|
||||
text: 'GitHub Repo',
|
||||
link: 'https://github.com/LBRYFoundation/lbry.org'
|
||||
}]
|
||||
},
|
||||
{
|
||||
title: 'Other Sites',
|
||||
rows: [{
|
||||
text: 'LBRY.com',
|
||||
link: 'https://lbry.com/'
|
||||
},
|
||||
{
|
||||
text: 'LBRY.tech',
|
||||
link: 'https://lbry.tech/'
|
||||
},
|
||||
{
|
||||
text: 'LBRY.fund',
|
||||
link: 'https://lbry.fund/'
|
||||
},
|
||||
{
|
||||
text: 'LBRY.tv',
|
||||
link: 'https://lbry.tv/'
|
||||
}]
|
||||
}
|
||||
],
|
||||
finePrints: [
|
||||
'© 2021 LBRY Foundation Inc',
|
||||
'With love for community'
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const group of Object.values(config.themeConfig.sidebar)) {
|
||||
for (const section of group) {
|
||||
if (section.collapsable) continue;
|
||||
section.collapsable = false;
|
||||
}
|
||||
}
|
||||
module.exports = config;
|
71
docs/.vuepress/plugins/redirect.js
Normal file
|
@ -0,0 +1,71 @@
|
|||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
|
||||
function getTemplate (path) {
|
||||
const result = '<!DOCTYPE html>' +
|
||||
'<html>' +
|
||||
'<head>' +
|
||||
'<meta charset="utf-8">' +
|
||||
'<title>Redirecting...</title>' +
|
||||
'<link rel="canonical" href="' + path + '">' +
|
||||
'<meta http-equiv="refresh" content="0; url=' + path + '">' +
|
||||
'</head>' +
|
||||
'</html>';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function getAliases (options, ctx) {
|
||||
let aliasArray = [];
|
||||
|
||||
ctx.pages.filter(({ frontmatter }) => {
|
||||
return frontmatter.alias || frontmatter.aliases
|
||||
}).forEach(page => {
|
||||
let aliases = page.frontmatter.alias || page.frontmatter.aliases;
|
||||
if (!Array.isArray(aliases)) aliases = [aliases];
|
||||
if (!aliases.length) return;
|
||||
|
||||
aliasArray.push({ url: page.path, aliases });
|
||||
});
|
||||
|
||||
if (options && Array.isArray(options))
|
||||
aliasArray = aliasArray.concat(options);
|
||||
|
||||
return aliasArray;
|
||||
}
|
||||
|
||||
// function getAbsLink (options, ctx, link) {
|
||||
// const alias = getAliases(options, ctx).find(link => link.aliases.includes(link));
|
||||
// return alias ? alias.url : link;
|
||||
// }
|
||||
|
||||
module.exports = (options, ctx) => ({
|
||||
name: 'redirect-pages',
|
||||
extendPageData($page) {
|
||||
Object.assign($page.frontmatter, { _aliases: getAliases(options, ctx) });
|
||||
},
|
||||
beforeDevServer(app) {
|
||||
getAliases(options, ctx).forEach(({ url, aliases }) =>
|
||||
aliases.forEach(alias =>
|
||||
app.get(alias, (_, res) => res.redirect(url)))
|
||||
);
|
||||
},
|
||||
generated() {
|
||||
const { outDir } = ctx;
|
||||
|
||||
getAliases(options, ctx).forEach(({ url, aliases }) => {
|
||||
aliases.forEach(alias => {
|
||||
let filePaths = [alias];
|
||||
if (/^\/.+\/$/.test(alias))
|
||||
filePaths = [
|
||||
alias.slice(1).replace(/\/$/, '') + '.html',
|
||||
alias.slice(1).replace(/\/$/, '') + '/index.html'
|
||||
];
|
||||
filePaths.forEach(async file => {
|
||||
const aliasPagePath = path.resolve(outDir, file)
|
||||
await fs.outputFile(aliasPagePath, getTemplate(url))
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
})
|
6
docs/.vuepress/plugins/richmeta.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
name: 'rich-meta',
|
||||
clientRootMixin: path.resolve(__dirname, 'richmeta.mixin.js')
|
||||
}
|
106
docs/.vuepress/plugins/richmeta.mixin.js
Normal file
|
@ -0,0 +1,106 @@
|
|||
|
||||
export default {
|
||||
created () {
|
||||
if (this.$ssrContext) {
|
||||
const scriptTypes = this.getScriptTypes()
|
||||
this.$ssrContext.pageMeta = renderScriptTypes(scriptTypes)
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
this.currentScriptTypes = {}
|
||||
this.updateScriptTypes()
|
||||
},
|
||||
|
||||
methods: {
|
||||
updateScriptTypes (scriptTypes) {
|
||||
if (!scriptTypes) scriptTypes = this.getScriptTypes();
|
||||
|
||||
Object.keys(scriptTypes).forEach(t => {
|
||||
if (!hasScriptType(t)) addScriptType(t, ...scriptTypes[t]);
|
||||
else setScriptType(t, scriptTypes[t]);
|
||||
});
|
||||
|
||||
if (this.currentScriptTypes)
|
||||
Object.keys(this.currentScriptTypes).forEach(t => {
|
||||
if (hasScriptType(t) && !scriptTypes[t]) removeScriptType(t);
|
||||
});
|
||||
|
||||
this.currentScriptTypes = scriptTypes;
|
||||
},
|
||||
|
||||
getScriptTypes () {
|
||||
const scriptTypes = this.$page.frontmatter.scriptTypes || {};
|
||||
if (scriptTypes.faq) {
|
||||
scriptTypes.faq[1] = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'FAQPage',
|
||||
mainEntity: scriptTypes.faq[1].map(([q, a]) => ({
|
||||
'@type': 'Question',
|
||||
name: q,
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: a
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
if (scriptTypes.org) {
|
||||
scriptTypes.org[1] = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'Organization',
|
||||
url: scriptTypes.org[1][0],
|
||||
logo: scriptTypes.org[1][1],
|
||||
name: scriptTypes.org[1][2]
|
||||
}
|
||||
}
|
||||
return scriptTypes;
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
$page () {
|
||||
this.updateScriptTypes()
|
||||
}
|
||||
},
|
||||
|
||||
beforeDestroy () {
|
||||
updateScriptTypes({})
|
||||
}
|
||||
}
|
||||
|
||||
function hasScriptType (type) {
|
||||
return !!document.querySelector(`script[data-id='${type}']`);
|
||||
}
|
||||
|
||||
function removeScriptType (type) {
|
||||
document.head.removeChild(document.querySelector(`script[data-id='${type}']`))
|
||||
}
|
||||
|
||||
function addScriptType (type, props = {}, content = '') {
|
||||
const script = document.createElement('script');
|
||||
script.setAttribute('data-id', type);
|
||||
Object.keys(props).forEach(p => script.setAttribute(p, props[p]));
|
||||
script.innerHTML = typeof content === 'object' ? JSON.stringify(content) : content;
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
|
||||
function setScriptType (type, content) {
|
||||
document.querySelector(`script[type='${type}']`).innerHTML = content;
|
||||
}
|
||||
|
||||
function renderScriptTypes (scriptTypes) {
|
||||
if (!scriptTypes || !Object.keys(scriptTypes).length) return '';
|
||||
return Object.keys(scriptTypes).map(t => {
|
||||
const props = scriptTypes[t][0] || {}
|
||||
let content = ''
|
||||
if (typeof scriptTypes[t][1] === 'string') content = scriptTypes[t][1];
|
||||
if (typeof scriptTypes[t][1] === 'object') content = JSON.stringify(scriptTypes[t][1]);
|
||||
|
||||
let res = `<script data-id="${t}"`
|
||||
Object.keys(props).forEach(key => {
|
||||
res += ` ${key}="${props[key]}"`
|
||||
})
|
||||
return `${res}>${content}</script>`
|
||||
}).join('\n ')
|
||||
}
|
1
docs/.vuepress/public/CNAME
Normal file
|
@ -0,0 +1 @@
|
|||
lbry.org
|
9
docs/.vuepress/public/browserconfig.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square150x150logo src="/logo/mstile-150x150.png"/>
|
||||
<TileColor>#27e4eb</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
BIN
docs/.vuepress/public/favicon.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
docs/.vuepress/public/logo-fit.png
Normal file
After Width: | Height: | Size: 28 KiB |
1
docs/.vuepress/public/logo-fit.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 595.28 514.73"><defs><style>.cls-1{fill:url(#linear-gradient);}.cls-2{mask:url(#mask);}.cls-3{fill:#52c5d2;}</style><linearGradient id="linear-gradient" x1="295.62" y1="334.7" x2="295.62" y2="44.07" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="0.12" stop-color="#e9e9e9"/><stop offset="0.36" stop-color="#afafaf"/><stop offset="0.71" stop-color="#545454"/><stop offset="1" stop-color="#010101"/></linearGradient><mask id="mask" x="-38.72" y="-29.4" width="668.69" height="553.16" maskUnits="userSpaceOnUse"><rect class="cls-1" x="-38.72" y="-29.4" width="668.69" height="553.16"/></mask></defs><title>lbry</title><g id="Layer_2" data-name="Layer 2"><g class="cls-2"><path class="cls-3" d="M585.81,324.31,294.2,478.2,13.61,326.67,0,356,294.3,514.73l301-160.45Zm-24.81-41L392.24,193.66V99.15H356.09v192.5L392.24,272V234.6L484,283.34,294.57,384,105.18,283.34l86.36-45.89v36.11L227.69,292V108.49H191.54v88L28.14,283.34,294.57,424.93ZM227.69,44.2H191.54V86.79h36.15Zm83.6,272.13V173.57H275.15V316.71l18.09,9.39Zm0-316.59H275.15v140h36.14Zm80.95,32.64H356.09V75h36.15Z"/></g></g></svg>
|
After Width: | Height: | Size: 1.2 KiB |
BIN
docs/.vuepress/public/logo-horizontal.png
Normal file
After Width: | Height: | Size: 16 KiB |
1
docs/.vuepress/public/logo-horizontal.svg
Normal file
After Width: | Height: | Size: 6 KiB |
BIN
docs/.vuepress/public/logo-vertical.png
Normal file
After Width: | Height: | Size: 47 KiB |
1
docs/.vuepress/public/logo-vertical.svg
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
docs/.vuepress/public/logo.png
Normal file
After Width: | Height: | Size: 29 KiB |
1
docs/.vuepress/public/logo.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 595.28 595.28"><defs><style>.cls-1{fill:url(#linear-gradient);}.cls-2{mask:url(#mask);}.cls-3{fill:#52c5d2;}</style><linearGradient id="linear-gradient" x1="295.62" y1="374.98" x2="295.62" y2="84.35" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff"/><stop offset="0.12" stop-color="#e9e9e9"/><stop offset="0.36" stop-color="#afafaf"/><stop offset="0.71" stop-color="#545454"/><stop offset="1" stop-color="#010101"/></linearGradient><mask id="mask" x="-38.72" y="10.87" width="668.69" height="553.16" maskUnits="userSpaceOnUse"><rect class="cls-1" x="-38.72" y="10.87" width="668.69" height="553.16"/></mask></defs><title>lbry-square</title><g id="Layer_2" data-name="Layer 2"><g class="cls-2"><path class="cls-3" d="M585.81,364.58,294.2,518.47,13.61,366.94,0,396.31,294.3,555l301-160.45Zm-24.81-41L392.24,233.94V139.43H356.09v192.5l36.15-19.71V274.87L484,323.62,294.57,424.27,105.18,323.62l86.36-45.9v36.11l36.15,18.42V148.76H191.54v88L28.14,323.62,294.57,465.2ZM227.69,84.47H191.54v42.59h36.15Zm83.6,272.13V213.85H275.15V357l18.09,9.4Zm0-316.58H275.15V180h36.14Zm80.95,32.64H356.09v42.59h36.15Z"/></g></g></svg>
|
After Width: | Height: | Size: 1.2 KiB |
BIN
docs/.vuepress/public/logo/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 8.6 KiB |
BIN
docs/.vuepress/public/logo/android-chrome-512x512.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
docs/.vuepress/public/logo/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 5.7 KiB |
BIN
docs/.vuepress/public/logo/favicon-16x16.png
Normal file
After Width: | Height: | Size: 1,009 B |
BIN
docs/.vuepress/public/logo/favicon-32x32.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
docs/.vuepress/public/logo/mstile-144x144.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
docs/.vuepress/public/logo/mstile-150x150.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
docs/.vuepress/public/logo/mstile-310x150.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
docs/.vuepress/public/logo/mstile-310x310.png
Normal file
After Width: | Height: | Size: 8.5 KiB |
BIN
docs/.vuepress/public/logo/mstile-70x70.png
Normal file
After Width: | Height: | Size: 3 KiB |
1468
docs/.vuepress/public/logo/safari-pinned-tab.svg
Normal file
After Width: | Height: | Size: 98 KiB |
22
docs/.vuepress/public/manifest.json
Normal file
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "LBRY Foundation",
|
||||
"short_name": "LBRY Foundation",
|
||||
"description": "LBRY is a secure, open, and community-run digital marketplace.",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/logo/android-chrome-192x192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "/logo/android-chrome-512x512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": "/?source=pwa",
|
||||
"background_color": "#072a46",
|
||||
"display": "minimal-ui",
|
||||
"scope": "/",
|
||||
"theme_color": "#27e4eb"
|
||||
}
|
12
docs/.vuepress/sidebar.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
module.exports = {
|
||||
// '/other/': [
|
||||
// {
|
||||
// title: 'Additional Information',
|
||||
// children: [
|
||||
// '/other/',
|
||||
// '/',
|
||||
// ['https://github.com/LBRYFoundation', 'Outside link']
|
||||
// ],
|
||||
// },
|
||||
// ]
|
||||
};
|
4072
docs/.vuepress/styles/animate.styl
vendored
Normal file
250
docs/.vuepress/styles/index.styl
Normal file
|
@ -0,0 +1,250 @@
|
|||
@import './animate'
|
||||
@import '~@fontsource/roboto/300.css'
|
||||
@import '~@fontsource/roboto/400.css'
|
||||
@import '~@fontsource/roboto/500.css'
|
||||
@import '~@fontsource/roboto/700.css'
|
||||
@import '~@fontsource/roboto/400-italic.css'
|
||||
@import '~@fontsource/roboto/500-italic.css'
|
||||
|
||||
table
|
||||
overflow visible
|
||||
|
||||
.animate__animated
|
||||
animation-fill-mode both
|
||||
|
||||
html
|
||||
background-color var(--primaryBG)
|
||||
body
|
||||
font-family Roboto, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Cantarell, 'Fira Sans' , 'Droid Sans' , 'Helvetica Neue', sans-serif;
|
||||
#app
|
||||
background-color var(--primaryBG)
|
||||
color var(--text)
|
||||
h2
|
||||
border-color var(--tertiaryBG)
|
||||
h1, h2, h3, h4, h5, h6
|
||||
color var(--headerText)
|
||||
.sidebar
|
||||
background-color var(--secondaryBG)
|
||||
border none
|
||||
.nav-links
|
||||
background-color var(--secondaryBG)
|
||||
border-color var(--tertiaryBG)
|
||||
&::-webkit-scrollbar-track
|
||||
background-color var(--tertiaryBG)
|
||||
border-radius 10px
|
||||
border 3px solid var(--secondaryBG)
|
||||
&::-webkit-scrollbar-thumb
|
||||
background-color var(--primaryBG)
|
||||
border-radius 10px
|
||||
border 3px solid var(--secondaryBG)
|
||||
a.sidebar-link:not(.active):not(:hover)
|
||||
color var(--secondaryText)
|
||||
.page-nav .inner
|
||||
border-top 1px solid var(--tertiaryBG)
|
||||
.page-edit .edit-link a, .page-edit .last-updated .prefix
|
||||
color var(--secondaryText)
|
||||
*::-webkit-scrollbar
|
||||
width 15px
|
||||
*::-webkit-scrollbar-track
|
||||
background-color var(--secondaryBG)
|
||||
border-radius 10px
|
||||
border 3px solid var(--primaryBG)
|
||||
*::-webkit-scrollbar-thumb
|
||||
background-color var(--tertiaryBG)
|
||||
border-radius 10px
|
||||
border 3px solid var(--primaryBG)
|
||||
.theme-default-content
|
||||
code
|
||||
color var(--secondaryText)
|
||||
background-color var(--secondaryBG)
|
||||
table
|
||||
tr
|
||||
border-top 1px solid var(--tertiaryBG)
|
||||
&:nth-child(2n)
|
||||
background-color var(--secondaryBG)
|
||||
th, td
|
||||
border 1px solid var(--tertiaryBG)
|
||||
padding .6em 1em
|
||||
[class^='language-']
|
||||
background-color var(--text)
|
||||
.custom-block
|
||||
color var(--text)
|
||||
border-radius 10px
|
||||
overflow hidden
|
||||
.custom-block-title
|
||||
font-size 18px
|
||||
font-weight 500
|
||||
&.tip, &.details, &.warning, &.danger
|
||||
color var(--text)
|
||||
background-color alpha(#000, 0.2)
|
||||
&.tip, &.details
|
||||
border-color var(--accent)
|
||||
.custom-block-title
|
||||
color var(--headerText)
|
||||
&.warning
|
||||
border-color var(--warning)
|
||||
.custom-block-title
|
||||
color var(--warning)
|
||||
a
|
||||
color var(--accent)
|
||||
&.danger
|
||||
border-color var(--error)
|
||||
.custom-block-title
|
||||
color var(--error)
|
||||
a
|
||||
color var(--accent)
|
||||
.sidebar-link
|
||||
&.active
|
||||
border none
|
||||
.sidebar-heading.open
|
||||
color var(--headerText) !important
|
||||
|
||||
// Lightbox
|
||||
.lightbox__default-loader {
|
||||
position:absolute;
|
||||
top:50%;
|
||||
left:50%;
|
||||
-webkit-transform:translate(-50%,-50%);
|
||||
transform:translate(-50%,-50%);
|
||||
z-index:-1
|
||||
}
|
||||
|
||||
.lightbox__default-loader__element {
|
||||
-webkit-animation:LightboxDefaultLoaderAnimation 1s linear infinite;
|
||||
animation:LightboxDefaultLoaderAnimation 1s linear infinite;
|
||||
border:3px solid #292929;
|
||||
border-top:3px solid #fff;
|
||||
border-radius:50%;
|
||||
height:75px;
|
||||
width:75px
|
||||
}
|
||||
|
||||
@-webkit-keyframes LightboxDefaultLoaderAnimation{
|
||||
to {
|
||||
border-top-color:#fff;
|
||||
-webkit-transform:rotate(1turn);
|
||||
transform:rotate(1turn)
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes LightboxDefaultLoaderAnimation{
|
||||
to{
|
||||
border-top-color:#fff;
|
||||
-webkit-transform:rotate(1turn);
|
||||
transform:rotate(1turn)
|
||||
}
|
||||
}
|
||||
|
||||
.lightbox {
|
||||
position:fixed;
|
||||
top: $navbarHeight;
|
||||
left:0;
|
||||
background:rgba(0,0,0,.8);
|
||||
display:-webkit-box;
|
||||
display:-ms-flexbox;
|
||||
display:flex;
|
||||
-webkit-box-pack:center;
|
||||
-ms-flex-pack:center;
|
||||
justify-content:center;
|
||||
-webkit-box-align:center;
|
||||
-ms-flex-align:center;
|
||||
align-items:center;
|
||||
z-index:1
|
||||
}
|
||||
|
||||
.lightbox__thumbnail {
|
||||
width:100%;
|
||||
height:100%
|
||||
}
|
||||
|
||||
.lightbox {
|
||||
width: 100%;
|
||||
height: calc(100% - 3.6rem)
|
||||
}
|
||||
|
||||
.lightbox__thumbnail img {
|
||||
width:100%
|
||||
}
|
||||
|
||||
.lightbox__close {
|
||||
position:fixed;
|
||||
right:0;
|
||||
top: $navbarHeight;
|
||||
padding:1rem;
|
||||
font-size:1.5rem;
|
||||
cursor:pointer;
|
||||
color:#fff;
|
||||
width:4rem;
|
||||
height:4rem
|
||||
}
|
||||
|
||||
.lightbox__arrow--invisible {
|
||||
visibility:hidden
|
||||
}
|
||||
|
||||
.lightbox__element {
|
||||
width:100%;
|
||||
height:-webkit-fit-content;
|
||||
height:-moz-fit-content;
|
||||
height:fit-content
|
||||
}
|
||||
|
||||
.lightbox__arrow,.lightbox__element {
|
||||
display:-webkit-box;
|
||||
display:-ms-flexbox;
|
||||
display:flex
|
||||
}
|
||||
|
||||
.lightbox__arrow {
|
||||
padding:0 2rem;
|
||||
cursor:pointer;
|
||||
-webkit-box-pack:center;
|
||||
-ms-flex-pack:center;
|
||||
justify-content:center;
|
||||
-webkit-box-align:center;
|
||||
-ms-flex-align:center;
|
||||
align-items:center
|
||||
}
|
||||
|
||||
.lightbox__arrow svg {
|
||||
fill:#fff;
|
||||
pointer-events:none
|
||||
}
|
||||
|
||||
.lightbox__image {
|
||||
-webkit-box-flex:1;
|
||||
-ms-flex:1;
|
||||
flex:1
|
||||
}
|
||||
|
||||
.lightbox__image img{
|
||||
width:100%;
|
||||
height:auto!important
|
||||
}
|
||||
|
||||
@media screen and (max-width:720px) {
|
||||
.lightbox__arrow{
|
||||
padding:0 1rem
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width:500px) {
|
||||
.lightbox__element{
|
||||
position:relative
|
||||
}
|
||||
.lightbox__arrow{
|
||||
position:absolute;
|
||||
padding:0 2rem;
|
||||
height:100%
|
||||
}
|
||||
.lightbox__arrow--right{
|
||||
right:0;
|
||||
background:-webkit-gradient(linear,left top,right top,from(transparent),to(rgba(0,0,0,.3)));
|
||||
background:linear-gradient(90deg,transparent,rgba(0,0,0,.3))
|
||||
}
|
||||
.lightbox__arrow--left{
|
||||
left:0;
|
||||
background:-webkit-gradient(linear,right top,left top,from(transparent),to(rgba(0,0,0,.3)));
|
||||
background:linear-gradient(270deg,transparent,rgba(0,0,0,.3))
|
||||
}
|
||||
}
|
40
docs/.vuepress/styles/palette.styl
Normal file
|
@ -0,0 +1,40 @@
|
|||
// layout
|
||||
$navbarHeight = 4rem
|
||||
$sidebarWidth = 20rem
|
||||
$contentWidth = 740px
|
||||
$homePageWidth = 1440px
|
||||
$navbar-vertical-padding = 0.7rem
|
||||
$navbar-horizontal-padding = 2.5rem
|
||||
|
||||
// responsive breakpoints
|
||||
$MQNarrow = 959px
|
||||
$MQMobile = 719px
|
||||
$MQMobileNarrow = 419px
|
||||
|
||||
// LBRY
|
||||
$accentColor = #27E4EB
|
||||
$counter-accent = #fff
|
||||
$warning = #F1C40F
|
||||
$error = #E74C3C
|
||||
$bg1 = #072A46
|
||||
$bg2 = #051D31
|
||||
$bg3 = #041523
|
||||
$header-text = #FAFAFA
|
||||
$text = #DDDDDD
|
||||
|
||||
:root {
|
||||
--accent: $accentColor
|
||||
--accentLight10: lighten($accentColor, 10%)
|
||||
--accentDark10: darken($accentColor, 10%)
|
||||
--counterAccent: $counter-accent
|
||||
|
||||
--tip: $accent
|
||||
--warning: $warning
|
||||
--error: $error
|
||||
|
||||
--primaryBG: $bg1
|
||||
--secondaryBG: $bg2
|
||||
--tertiaryBG: $bg3
|
||||
--headerText: $header-text
|
||||
--text: $text
|
||||
}
|
101
docs/.vuepress/theme/components/Footer.vue
Normal file
|
@ -0,0 +1,101 @@
|
|||
<template>
|
||||
<div class="footer">
|
||||
<div class="footer-main">
|
||||
<img v-if="config.logo" :src="config.logo" draggable="false" />
|
||||
<div class="columns" v-if="config.columns && config.columns.length">
|
||||
<div class="column" :key="i" v-for="(column, i) in config.columns">
|
||||
<span class="col-title">{{ column.title }}</span>
|
||||
<div class="links" v-if="column.rows">
|
||||
<NavLink :key="j" v-for="(cell, j) in column.rows" :item="cell" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fine-print" v-if="config.finePrints">
|
||||
<span>{{ config.finePrints[0] }}</span> <i>{{ config.finePrints[1] }}</i>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NavLink from '@theme/components/NavLink.vue'
|
||||
export default {
|
||||
name: 'Footer',
|
||||
components: { NavLink },
|
||||
computed: {
|
||||
data () {
|
||||
return this.$page.frontmatter
|
||||
},
|
||||
config () {
|
||||
return this.$site.themeConfig.footer || {}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
.footer
|
||||
background-color var(--tertiaryBG)
|
||||
background-repeat no-repeat
|
||||
background-size contain
|
||||
background-position right
|
||||
padding 1rem
|
||||
width calc(100% - 2rem)
|
||||
margin-top 5rem
|
||||
.footer-main
|
||||
display flex
|
||||
flex-direction row
|
||||
justify-content space-between
|
||||
max-width $contentWidth
|
||||
margin 0 auto
|
||||
img
|
||||
flex none
|
||||
height 100px
|
||||
.columns
|
||||
display flex
|
||||
gap 40px
|
||||
.column-opener
|
||||
max-width 200px
|
||||
.column
|
||||
display flex
|
||||
flex-direction column
|
||||
.col-title
|
||||
font-weight 500
|
||||
margin-bottom 5px
|
||||
color var(--headerText)
|
||||
.links
|
||||
display flex
|
||||
align-self center
|
||||
flex-direction column
|
||||
align-self flex-start
|
||||
a
|
||||
font-weight 400
|
||||
color var(--text)
|
||||
& svg
|
||||
display none
|
||||
&:hover
|
||||
text-decoration underline
|
||||
.fine-print
|
||||
color var(--text)
|
||||
font-size 10px
|
||||
max-width $contentWidth
|
||||
margin 0 auto
|
||||
margin-top 30px
|
||||
display flex
|
||||
gap 10px
|
||||
@media (max-width: $MQMobile)
|
||||
.footer
|
||||
background-image none
|
||||
.columns
|
||||
flex-wrap wrap
|
||||
gap 20px
|
||||
.column-opener
|
||||
max-width none
|
||||
margin-bottom 2rem
|
||||
.column
|
||||
align-self flex-start
|
||||
.links
|
||||
justify-content center
|
||||
.fine-print
|
||||
margin-top 2rem
|
||||
</style>
|
153
docs/.vuepress/theme/components/Home.vue
Normal file
|
@ -0,0 +1,153 @@
|
|||
<template>
|
||||
<main class="home" role="main">
|
||||
<header class="landing">
|
||||
<div class="hero">
|
||||
<img :src="data.heroImage" draggable="false" />
|
||||
<div class="hero-text">
|
||||
<h1>{{ data.heroText || $title || 'Hello' }}</h1>
|
||||
<p class="description">{{ data.tagline || $description || 'Welcome to your VuePress site' }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="action-buttons" v-if="data.actionButtons && data.actionButtons.length">
|
||||
<a
|
||||
class="action-button"
|
||||
v-for="abtn in data.actionButtons"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
:key="abtn.text"
|
||||
:href="abtn.link"
|
||||
>
|
||||
<IconifyIcon v-if="abtn.icon" :icon="abtn.icon" />
|
||||
<span>{{ abtn.text }}</span>
|
||||
</a>
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<Content class="content" />
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Icon, addCollection } from '@iconify/vue2'
|
||||
|
||||
import faSolidIcons from '@iconify/json/json/fa-solid.json';
|
||||
addCollection(faSolidIcons);
|
||||
|
||||
import faBrandsIcons from '@iconify/json/json/fa-brands.json';
|
||||
addCollection(faBrandsIcons);
|
||||
|
||||
export default {
|
||||
name: 'Home',
|
||||
components: { IconifyIcon: Icon },
|
||||
computed: {
|
||||
data () {
|
||||
return this.$page.frontmatter
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
|
||||
.home
|
||||
padding $navbarHeight 0
|
||||
margin 0 auto
|
||||
display flex
|
||||
flex-direction column
|
||||
position relative
|
||||
.landing
|
||||
display flex
|
||||
flex-direction column
|
||||
justify-content space-between
|
||||
margin 2.5rem 0
|
||||
.hero
|
||||
display flex
|
||||
flex-direction column
|
||||
text-align center
|
||||
align-self center
|
||||
justify-content center
|
||||
align-items center
|
||||
gap 20px
|
||||
max-width $contentWidth - 100px
|
||||
width calc(100% - 40px)
|
||||
img
|
||||
width 200px
|
||||
flex none
|
||||
.hero-text
|
||||
display flex
|
||||
flex-direction column
|
||||
text-align center
|
||||
align-self center
|
||||
justify-content center
|
||||
align-items center
|
||||
gap 10px
|
||||
h1
|
||||
font-size 48px
|
||||
margin 0
|
||||
.description
|
||||
width 100%
|
||||
font-size 26px
|
||||
line-height 1.3
|
||||
color var(--text)
|
||||
margin 0
|
||||
.action-buttons
|
||||
display flex
|
||||
justify-content space-evenly
|
||||
align-self center
|
||||
flex-wrap wrap
|
||||
gap 20px
|
||||
.action-button
|
||||
display inline-flex
|
||||
align-items center
|
||||
gap 10px
|
||||
padding 15px 20px
|
||||
font-size 20px
|
||||
font-weight 500
|
||||
flex-direction row
|
||||
color var(--counterAccent)
|
||||
background-color var(--tertiaryBG)
|
||||
border-radius 8px
|
||||
line-height 1
|
||||
&:hover
|
||||
background-color var(--secondaryBG)
|
||||
text-decoration none
|
||||
.content
|
||||
background-color var(--secondaryBG)
|
||||
border-radius 15px
|
||||
box-shadow 0px 0px 4px rgba(0, 0, 0, 0.25)
|
||||
padding 20px
|
||||
margin 0 auto
|
||||
max-width $contentWidth
|
||||
width calc(100% - 80px)
|
||||
& > :first-child
|
||||
margin-top 0
|
||||
& > :last-child
|
||||
margin-bottom 0
|
||||
hr
|
||||
margin 0
|
||||
// @media (max-width: $MQNarrow)
|
||||
@media (max-width: $MQMobile)
|
||||
.home
|
||||
padding-bottom 0
|
||||
.landing
|
||||
.hero
|
||||
img
|
||||
width 150px
|
||||
.hero-text
|
||||
h1
|
||||
font-size 24px
|
||||
.description
|
||||
font-size 20px
|
||||
.action-buttons
|
||||
gap 10px
|
||||
.action-button
|
||||
gap 10px
|
||||
padding 10px 15px
|
||||
font-size 18px
|
||||
.content
|
||||
border-radius 0
|
||||
box-shadow none
|
||||
width calc(100% - 40px)
|
||||
& + .footer
|
||||
margin-top 0
|
||||
</style>
|
85
docs/.vuepress/theme/components/NavLink.vue
Normal file
|
@ -0,0 +1,85 @@
|
|||
<template>
|
||||
<RouterLink
|
||||
v-if="isInternal"
|
||||
class="nav-link"
|
||||
role="button"
|
||||
:class="item.class || ''"
|
||||
:to="link"
|
||||
:exact="exact"
|
||||
@focusout.native="focusoutAction"
|
||||
>
|
||||
{{ item.text }}
|
||||
</RouterLink>
|
||||
<a
|
||||
v-else
|
||||
:href="link"
|
||||
class="nav-link external"
|
||||
role="button"
|
||||
:class="item.class || ''"
|
||||
:target="target"
|
||||
:rel="rel"
|
||||
@focusout="focusoutAction"
|
||||
>
|
||||
{{ item.text }}
|
||||
<OutboundLink v-if="isBlankTarget" />
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { isExternal, isMailto, isTel, ensureExt } from '@parent-theme/util'
|
||||
export default {
|
||||
name: 'NavLink',
|
||||
props: {
|
||||
item: {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
absLink () {
|
||||
const alias = this.$page.frontmatter._aliases ? this.$page.frontmatter._aliases.find(link => link.aliases.includes(this.item.link)) : null;
|
||||
return alias ? alias.url : this.item.link;
|
||||
},
|
||||
link () {
|
||||
return ensureExt(this.absLink)
|
||||
},
|
||||
exact () {
|
||||
if (this.$site.locales) {
|
||||
return Object.keys(this.$site.locales).some(rootLink => rootLink === this.link)
|
||||
}
|
||||
return this.link === '/'
|
||||
},
|
||||
isNonHttpURI () {
|
||||
return isMailto(this.link) || isTel(this.link)
|
||||
},
|
||||
isBlankTarget () {
|
||||
return this.target === '_blank'
|
||||
},
|
||||
isInternal () {
|
||||
return !isExternal(this.link) && !this.isBlankTarget
|
||||
},
|
||||
target () {
|
||||
if (this.isNonHttpURI) {
|
||||
return null
|
||||
}
|
||||
if (this.item.target) {
|
||||
return this.item.target
|
||||
}
|
||||
return isExternal(this.link) ? '_blank' : ''
|
||||
},
|
||||
rel () {
|
||||
if (this.isNonHttpURI) {
|
||||
return null
|
||||
}
|
||||
if (this.item.rel) {
|
||||
return this.item.rel
|
||||
}
|
||||
return this.isBlankTarget ? 'noopener noreferrer' : ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
focusoutAction () {
|
||||
this.$emit('focusout')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
149
docs/.vuepress/theme/components/Navbar.vue
Normal file
|
@ -0,0 +1,149 @@
|
|||
<template>
|
||||
<header class="navbar" role="navigation">
|
||||
<SidebarButton @toggle-sidebar="$emit('toggle-sidebar')" role="button" />
|
||||
|
||||
<RouterLink
|
||||
:to="$localePath"
|
||||
class="home-link"
|
||||
>
|
||||
<img
|
||||
v-if="$site.themeConfig.logo"
|
||||
class="logo"
|
||||
:src="$site.themeConfig.logo"
|
||||
:alt="$siteTitle"
|
||||
>
|
||||
<span
|
||||
v-if="$siteTitle"
|
||||
ref="siteName"
|
||||
class="site-name"
|
||||
>{{ $siteTitle }}</span>
|
||||
</RouterLink>
|
||||
|
||||
<div
|
||||
class="links"
|
||||
:style="linksWrapMaxWidth ? {
|
||||
'max-width': linksWrapMaxWidth + 'px'
|
||||
} : {}"
|
||||
>
|
||||
<AlgoliaSearchBox
|
||||
v-if="isAlgoliaSearch"
|
||||
role="search"
|
||||
:options="algolia"
|
||||
/>
|
||||
<SearchBox v-else-if="$site.themeConfig.search !== false && $page.frontmatter.search !== false" />
|
||||
<NavLinks class="can-hide" />
|
||||
</div>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AlgoliaSearchBox from '@AlgoliaSearchBox'
|
||||
import SearchBox from '@SearchBox'
|
||||
import SidebarButton from '@parent-theme/components/SidebarButton.vue'
|
||||
import NavLinks from '@parent-theme/components/NavLinks.vue'
|
||||
export default {
|
||||
name: 'Navbar',
|
||||
components: {
|
||||
SidebarButton,
|
||||
NavLinks,
|
||||
SearchBox,
|
||||
AlgoliaSearchBox
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
linksWrapMaxWidth: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
algolia () {
|
||||
return this.$themeLocaleConfig.algolia || this.$site.themeConfig.algolia || {}
|
||||
},
|
||||
isAlgoliaSearch () {
|
||||
return this.algolia && this.algolia.apiKey && this.algolia.indexName
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
const MOBILE_DESKTOP_BREAKPOINT = 719 // refer to config.styl
|
||||
const NAVBAR_VERTICAL_PADDING = parseInt(css(this.$el, 'paddingLeft')) + parseInt(css(this.$el, 'paddingRight'))
|
||||
const handleLinksWrapWidth = () => {
|
||||
if (document.documentElement.clientWidth < MOBILE_DESKTOP_BREAKPOINT) {
|
||||
this.linksWrapMaxWidth = null
|
||||
} else {
|
||||
this.linksWrapMaxWidth = this.$el.offsetWidth - NAVBAR_VERTICAL_PADDING
|
||||
- (this.$refs.siteName && this.$refs.siteName.offsetWidth || 0)
|
||||
}
|
||||
}
|
||||
handleLinksWrapWidth()
|
||||
// deepscan-disable-next-line VUE_MISSING_CLEANUP_IN_LIFECYCLE
|
||||
window.addEventListener('resize', handleLinksWrapWidth, false)
|
||||
}
|
||||
}
|
||||
function css (el, property) {
|
||||
// NOTE: Known bug, will return 'auto' if style value is 'auto'
|
||||
const win = el.ownerDocument.defaultView
|
||||
// null means not to return pseudo styles
|
||||
return win.getComputedStyle(el, null)[property]
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
.navbar, .sidebar .nav-links
|
||||
.nav-link
|
||||
color var(--headerText)
|
||||
font-weight 300
|
||||
&.router-link-active
|
||||
font-weight 500
|
||||
& svg
|
||||
display none
|
||||
&:hover, &.router-link-active
|
||||
color var(--accent)
|
||||
.navbar
|
||||
padding $navbar-vertical-padding $navbar-horizontal-padding
|
||||
line-height $navbarHeight - 1.4rem
|
||||
background-color var(--tertiaryBG)
|
||||
border none
|
||||
a, span, img
|
||||
display inline-block
|
||||
.logo
|
||||
height $navbarHeight - 1.4rem
|
||||
min-width $navbarHeight - 1.4rem
|
||||
margin-right 0.8rem
|
||||
vertical-align top
|
||||
.site-name
|
||||
font-size 1.3rem
|
||||
font-weight 600
|
||||
color var(--headerText)
|
||||
position relative
|
||||
display none
|
||||
.links
|
||||
padding-left 1.5rem
|
||||
box-sizing border-box
|
||||
white-space nowrap
|
||||
font-size 0.9rem
|
||||
position absolute
|
||||
right $navbar-horizontal-padding
|
||||
top $navbar-vertical-padding
|
||||
display flex
|
||||
.search-box
|
||||
flex: 0 0 auto
|
||||
vertical-align top
|
||||
@media (max-width: $MQMobile)
|
||||
.navbar
|
||||
padding-left 4rem
|
||||
.can-hide
|
||||
display none
|
||||
.links
|
||||
padding-left 1.5rem
|
||||
.site-name
|
||||
width calc(100vw - 11.4rem)
|
||||
overflow hidden
|
||||
white-space nowrap
|
||||
text-overflow ellipsis
|
||||
@media (min-width: $MQMobile)
|
||||
.nav-links a
|
||||
&:hover, &.router-link-active
|
||||
color var(--accent)
|
||||
.nav-item > a:not(.external)
|
||||
&:hover, &.router-link-active
|
||||
border none
|
||||
</style>
|
3
docs/.vuepress/theme/index.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
extend: '@vuepress/theme-default'
|
||||
}
|
101
docs/.vuepress/theme/layouts/404.vue
Normal file
|
@ -0,0 +1,101 @@
|
|||
<template>
|
||||
<div class="error-page">
|
||||
<img src="/logo-fit.svg">
|
||||
<div class="content">
|
||||
<h1>Oh no!</h1>
|
||||
<p class="description">The page you have requested could not be found.</p>
|
||||
<div class="action-buttons">
|
||||
<RouterLink
|
||||
class="action-button"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
:to="'/'"
|
||||
>
|
||||
<IconifyIcon icon="fa-solid:arrow-circle-left" />
|
||||
<span>Go Back Home</span>
|
||||
</RouterLink>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="stylus">
|
||||
.error-page
|
||||
padding 2rem 2.5rem
|
||||
display flex
|
||||
flex-direction column
|
||||
justify-content center
|
||||
align-items center
|
||||
text-align center
|
||||
gap 40px
|
||||
width auto
|
||||
height calc(100vh - 4rem)
|
||||
& > img
|
||||
filter grayscale()
|
||||
width 200px
|
||||
flex none
|
||||
.content
|
||||
display flex
|
||||
flex-direction column
|
||||
justify-content center
|
||||
align-items center
|
||||
gap 10px
|
||||
h1
|
||||
font-size 48px
|
||||
margin 0
|
||||
.description
|
||||
width 100%
|
||||
font-size 26px
|
||||
line-height 1.3
|
||||
color var(--text)
|
||||
margin 0
|
||||
.action-buttons
|
||||
display flex
|
||||
justify-content space-evenly
|
||||
align-self center
|
||||
flex-wrap wrap
|
||||
gap 20px
|
||||
.action-button
|
||||
display inline-flex
|
||||
align-items center
|
||||
gap 10px
|
||||
padding 15px 20px
|
||||
font-size 20px
|
||||
font-weight 500
|
||||
flex-direction row
|
||||
color var(--counterAccent)
|
||||
background-color var(--tertiaryBG)
|
||||
border-radius 8px
|
||||
line-height 1
|
||||
&:hover
|
||||
background-color var(--secondaryBG)
|
||||
text-decoration none
|
||||
|
||||
@media (max-width: $MQNarrow)
|
||||
.error-page
|
||||
padding 2rem
|
||||
|
||||
@media (max-width: $MQMobile)
|
||||
.error-page
|
||||
gap 20px
|
||||
& > img
|
||||
width 150px
|
||||
h1
|
||||
font-size 24px
|
||||
.description
|
||||
font-size 20px
|
||||
.action-buttons .action-button
|
||||
gap 10px
|
||||
padding 10px 15px
|
||||
font-size 18px
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { Icon, addCollection } from '@iconify/vue2'
|
||||
import faSolidIcons from '@iconify/json/json/fa-solid.json';
|
||||
addCollection(faSolidIcons);
|
||||
|
||||
export default {
|
||||
components: { IconifyIcon: Icon }
|
||||
}
|
||||
</script>
|
144
docs/.vuepress/theme/layouts/Layout.vue
Normal file
|
@ -0,0 +1,144 @@
|
|||
<template>
|
||||
<div
|
||||
class="theme-container"
|
||||
:class="pageClasses"
|
||||
@touchstart="onTouchStart"
|
||||
@touchend="onTouchEnd"
|
||||
>
|
||||
<Navbar
|
||||
v-if="shouldShowNavbar"
|
||||
@toggle-sidebar="toggleSidebar"
|
||||
/>
|
||||
|
||||
<div
|
||||
class="sidebar-mask"
|
||||
@click="toggleSidebar(false)"
|
||||
/>
|
||||
|
||||
<Sidebar
|
||||
:items="sidebarItems"
|
||||
@toggle-sidebar="toggleSidebar"
|
||||
>
|
||||
<template #top>
|
||||
<slot name="sidebar-top" />
|
||||
</template>
|
||||
<template #bottom>
|
||||
<slot name="sidebar-bottom" />
|
||||
</template>
|
||||
</Sidebar>
|
||||
|
||||
<Home v-if="$page.frontmatter.home" />
|
||||
|
||||
<Page
|
||||
v-else
|
||||
:sidebar-items="sidebarItems"
|
||||
>
|
||||
<template #top>
|
||||
<slot name="page-top" />
|
||||
</template>
|
||||
<template #bottom>
|
||||
<slot name="page-bottom" />
|
||||
</template>
|
||||
</Page>
|
||||
|
||||
<Footer v-if="$page.frontmatter.footer && $site.themeConfig.footer" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Home from '@theme/components/Home.vue'
|
||||
import Navbar from '@theme/components/Navbar.vue'
|
||||
import Page from '@parent-theme/components/Page.vue'
|
||||
import Sidebar from '@parent-theme/components/Sidebar.vue'
|
||||
import Footer from '@theme/components/Footer.vue'
|
||||
import { resolveSidebarItems } from '@parent-theme/util'
|
||||
export default {
|
||||
name: 'Layout',
|
||||
components: {
|
||||
Home,
|
||||
Page,
|
||||
Sidebar,
|
||||
Navbar,
|
||||
Footer
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
isSidebarOpen: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
shouldShowNavbar () {
|
||||
const { themeConfig } = this.$site
|
||||
const { frontmatter } = this.$page
|
||||
if (
|
||||
frontmatter.navbar === false
|
||||
|| themeConfig.navbar === false) {
|
||||
return false
|
||||
}
|
||||
return (
|
||||
this.$title
|
||||
|| themeConfig.logo
|
||||
|| themeConfig.repo
|
||||
|| themeConfig.nav
|
||||
|| this.$themeLocaleConfig.nav
|
||||
)
|
||||
},
|
||||
shouldShowSidebar () {
|
||||
const { frontmatter } = this.$page
|
||||
return (
|
||||
!frontmatter.home
|
||||
&& frontmatter.sidebar !== false
|
||||
&& this.sidebarItems.length
|
||||
)
|
||||
},
|
||||
sidebarItems () {
|
||||
return resolveSidebarItems(
|
||||
this.$page,
|
||||
this.$page.regularPath,
|
||||
this.$site,
|
||||
this.$localePath
|
||||
)
|
||||
},
|
||||
pageClasses () {
|
||||
const userPageClass = this.$page.frontmatter.pageClass
|
||||
return [
|
||||
{
|
||||
'no-navbar': !this.shouldShowNavbar,
|
||||
'sidebar-open': this.isSidebarOpen,
|
||||
'no-sidebar': !this.shouldShowSidebar
|
||||
},
|
||||
userPageClass
|
||||
]
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.$router.afterEach(() => {
|
||||
this.isSidebarOpen = false
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
toggleSidebar (to) {
|
||||
this.isSidebarOpen = typeof to === 'boolean' ? to : !this.isSidebarOpen
|
||||
this.$emit('toggle-sidebar', this.isSidebarOpen)
|
||||
},
|
||||
// side swipe
|
||||
onTouchStart (e) {
|
||||
this.touchStart = {
|
||||
x: e.changedTouches[0].clientX,
|
||||
y: e.changedTouches[0].clientY
|
||||
}
|
||||
},
|
||||
onTouchEnd (e) {
|
||||
const dx = e.changedTouches[0].clientX - this.touchStart.x
|
||||
const dy = e.changedTouches[0].clientY - this.touchStart.y
|
||||
if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 40) {
|
||||
if (dx > 0 && this.touchStart.x <= 80) {
|
||||
this.toggleSidebar(true)
|
||||
} else {
|
||||
this.toggleSidebar(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
27
docs/README.md
Normal file
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
home: true
|
||||
heroImage: /logo-fit.svg
|
||||
heroText: Welcome to LBRY.
|
||||
tagline: LBRY is a secure, open, and community-run digital marketplace.
|
||||
actionButtons:
|
||||
- text: Download LBRY
|
||||
icon: fa-solid:arrow-alt-circle-down
|
||||
link: https://lbry.com/get
|
||||
- text: Join Discord
|
||||
icon: fa-brands:discord
|
||||
link: https://chat.lbry.com/
|
||||
footer: true
|
||||
sitemap:
|
||||
changefreq: hourly
|
||||
priority: 0.8
|
||||
scriptTypes:
|
||||
org:
|
||||
- type: application/ld+json
|
||||
-
|
||||
- https://lbry.org
|
||||
- https://lbry.org/logo.png
|
||||
- LBRY Foundation
|
||||
---
|
||||
|
||||
<!-- TODO update with actual content -->
|
||||
Example text.
|
37
docs/governance/README.md
Normal file
|
@ -0,0 +1,37 @@
|
|||
# Governance
|
||||
The LBRY Foundation is a US-based non-profit corporation governed by a board of directors.
|
||||
<!-- TODO probably add more about the governance here -->
|
||||
|
||||
## Board of Directors
|
||||
<!-- TODO update images with real people -->
|
||||
<Person
|
||||
avatar="/logo.png"
|
||||
imageClass="rounded"
|
||||
name="Julie Sigwart"
|
||||
subtitle="Founding board member of LBRY Foundation, Inc."/>
|
||||
<Person
|
||||
avatar="/logo.png"
|
||||
imageClass="rounded"
|
||||
name="Jon Ringo"
|
||||
subtitle="First community elected board member of LBRY Foundation, Inc."/>
|
||||
<Person
|
||||
avatar="/logo.png"
|
||||
imageClass="rounded"
|
||||
name="Leo Rodrigues"
|
||||
subtitle="Second community elected board member of LBRY Foundation, Inc."/>
|
||||
<Person
|
||||
avatar="/logo.png"
|
||||
imageClass="rounded"
|
||||
name="Ralph Streb"
|
||||
subtitle="Second community elected board member of LBRY Foundation, Inc."/> <!-- TODO typo? -->
|
||||
|
||||
## Board Elections
|
||||
The first board election was the December 2019 Board Election, won by Jon Ringo.
|
||||
The second board election was the December 2020 Board Election, won by Ralph Streb and Leo Rodrigues.
|
||||
The board is expected to be add several more members through 2021.
|
||||
<!-- TODO more info? -->
|
||||
|
||||
## Future Structure
|
||||
The Foundation is expected to integrate network organization principles through 2020.
|
||||
The intent is to decentralize decision making and management powers throughout the LBRY network and community as they develop.
|
||||
<!-- TODO more info? -->
|
167
docs/privacy/README.md
Normal file
|
@ -0,0 +1,167 @@
|
|||
# Privacy Policy
|
||||
|
||||
This privacy policy has been compiled to better serve those who are concerned with how their 'Personally Identifiable Information' (PII) is being used online. PII, as described in US privacy law and information security, is information that can be used on its own or with other information to identify, contact, or locate a single person, or to identify an individual in context. Please read our privacy policy carefully to get a clear understanding of how we collect, use, protect or otherwise handle your Personally Identifiable Information in accordance with our website.
|
||||
|
||||
## What personal information do we collect from the people that visit our blog, website or app?
|
||||
|
||||
When ordering or registering on our site, as appropriate, you may be asked to enter your name, email address, mailing address, phone number, credit card information or other details to help you with your experience.
|
||||
|
||||
## When do we collect information?
|
||||
|
||||
We collect information from you when you register on our site, place an order, subscribe to a newsletter, respond to a survey, fill out a form, open a support ticket or enter information on our site, or provide us with feedback on our products or services.
|
||||
|
||||
## How do we use your information?
|
||||
|
||||
We may use the information we collect from you when you register, make a purchase, sign up for our newsletter, respond to a survey or marketing communication, surf the website, or use certain other site features in the following ways:
|
||||
|
||||
* To personalize your experience and to allow us to deliver the type of content and product offerings in which you are most interested.
|
||||
* To improve our website in order to better serve you.
|
||||
* To allow us to better service you in responding to your customer service requests.
|
||||
* To administer a contest, promotion, survey or other site feature.
|
||||
* To quickly process your transactions.
|
||||
* To send periodic emails regarding your order or other products and services.
|
||||
* To follow up with them after correspondence (live chat, email or phone inquiries)
|
||||
|
||||
## How do we protect your information?
|
||||
|
||||
* Our website is scanned on a regular basis for security holes and known vulnerabilities in order to make your visit to our site as safe as possible.
|
||||
|
||||
* We use regular Malware Scanning.
|
||||
|
||||
* Your personal information is contained behind secured networks and is only accessible by a limited number of persons who have special access rights to such systems, and are required to keep the information confidential. In addition, all sensitive/credit information you supply is encrypted via Secure Socket Layer (SSL) technology.
|
||||
|
||||
* We implement a variety of security measures when a user places an order enters, submits, or accesses their information to maintain the safety of your personal information.
|
||||
|
||||
* All transactions are processed through a gateway provider and are not stored or processed on our servers.
|
||||
|
||||
## Do we use "cookies"?
|
||||
|
||||
Yes. Cookies are small files that a site or its service provider transfers to your computer's hard drive through your Web browser (if you allow) that enables the site's or service provider's systems to recognize your browser and capture and remember certain information. For instance, we use cookies to help us remember and process the items in your shopping cart. They are also used to help us understand your preferences based on previous or current site activity, which enables us to provide you with improved services. We also use cookies to help us compile aggregate data about site traffic and site interaction so that we can offer better site experiences and tools in the future.
|
||||
|
||||
We use cookies to:
|
||||
|
||||
* Help remember and process the items in the shopping cart.
|
||||
* Compile aggregate data about site traffic and site interactions in order to offer better site experiences and tools in the future. We may also use trusted third-party services that * track this information on our behalf.
|
||||
* You can choose to have your computer warn you each time a cookie is being sent, or you can choose to turn off all cookies. You do this through your browser settings. Since browser is a little different, look at your browser's Help Menu to learn the correct way to modify your cookies.
|
||||
|
||||
### If users disable cookies in their browser:
|
||||
|
||||
If you turn cookies off it will turn off some of the features of the site.
|
||||
|
||||
## Third-party disclosure
|
||||
|
||||
We do not sell, trade, or otherwise transfer to outside parties your Personally Identifiable Information unless we provide users with advance notice. This does not include website hosting partners and other parties who assist us in operating our website, conducting our business, or serving our users, so long as those parties agree to keep this information confidential. We may also release information when it's release is appropriate to comply with the law, enforce our site policies, or protect ours or others' rights, property or safety.
|
||||
|
||||
However, non-personally identifiable visitor information may be provided to other parties for marketing, advertising, or other uses.
|
||||
|
||||
## Third-party links
|
||||
|
||||
Occasionally, at our discretion, we may include or offer third-party products or services on our website. These third-party sites have separate and independent privacy policies. We therefore have no responsibility or liability for the content and activities of these linked sites. Nonetheless, we seek to protect the integrity of our site and welcome any feedback about these sites.
|
||||
|
||||
### Google
|
||||
|
||||
Google's advertising requirements can be summed up by Google's Advertising Principles. They are put in place to provide a positive experience for users. https://support.google.com/adwordspolicy/answer/1316548?hl=en
|
||||
|
||||
We use Google AdSense Advertising on our website.
|
||||
|
||||
Google, as a third-party vendor, uses cookies to serve ads on our site. Google's use of the DART cookie enables it to serve ads to our users based on previous visits to our site and other sites on the Internet. Users may opt-out of the use of the DART cookie by visiting the Google Ad and Content Network privacy policy.
|
||||
|
||||
We have implemented the following:
|
||||
|
||||
* Remarketing with Google AdSense
|
||||
* Google Display Network Impression Reporting
|
||||
* Demographics and Interests Reporting
|
||||
* We, along with third-party vendors such as Google use first-party cookies (such as the Google Analytics cookies) and third-party cookies (such as the DoubleClick cookie) or other third-party identifiers together to compile data regarding user interactions with ad impressions and other ad service functions as they relate to our website.
|
||||
|
||||
## Opting out:
|
||||
Users can set preferences for how Google advertises to you using the Google Ad Settings page. Alternatively, you can opt out by visiting the Network Advertising Initiative Opt Out page or by using the Google Analytics Opt Out Browser add on.
|
||||
|
||||
## Google Forms
|
||||
We use Google Forms for manual input of data by users. Data input into Google Forms are subject to Google's Privacy policy listed [here](https://www.google.com/intl/en/policies/privacy/).
|
||||
|
||||
## California Online Privacy Protection Act
|
||||
|
||||
CalOPPA is the first state law in the nation to require commercial websites and online services to post a privacy policy. The law's reach stretches well beyond California to require any person or company in the United States (and conceivably the world) that operates websites collecting Personally Identifiable Information from California consumers to post a conspicuous privacy policy on its website stating exactly the information being collected and those individuals or companies with whom it is being shared. - See more at: http://consumercal.org/california-online-privacy-protection-act-caloppa/#sthash.0FdRbT51.dpuf
|
||||
|
||||
According to CalOPPA, we agree to the following:
|
||||
|
||||
* Users can visit our site anonymously.
|
||||
|
||||
* Once this privacy policy is created, we will add a link to it on our home page or as a minimum, on the first significant page after entering our website.
|
||||
|
||||
* Our Privacy Policy link includes the word 'Privacy' and can easily be found on the page specified above.
|
||||
|
||||
### You will be notified of any Privacy Policy changes:
|
||||
|
||||
Here, on our Privacy Policy Page.
|
||||
|
||||
|
||||
## You can change your personal information:
|
||||
|
||||
* By emailing us
|
||||
* By logging in to your account
|
||||
* By chatting with us or by sending us a support ticket
|
||||
|
||||
## How does our site handle Do Not Track signals?
|
||||
|
||||
We honor Do Not Track signals and Do Not Track, plant cookies, or use advertising when a Do Not Track (DNT) browser mechanism is in place.
|
||||
|
||||
## Does our site allow third-party behavioral tracking?
|
||||
|
||||
It's also important to note that we do not allow third-party behavioral tracking
|
||||
|
||||
## COPPA (Children Online Privacy Protection Act)
|
||||
|
||||
When it comes to the collection of personal information from children under the age of 13 years old, the Children's Online Privacy Protection Act (COPPA) puts parents in control. The Federal Trade Commission, United States' consumer protection agency, enforces the COPPA Rule, which spells out what operators of websites and online services must do to protect children's privacy and safety online.
|
||||
|
||||
We do not specifically market to children under the age of 13 years old.
|
||||
|
||||
Do we let third-parties, including ad networks or plug-ins collect PII from children under 13?
|
||||
|
||||
## Fair Information Practices
|
||||
|
||||
The Fair Information Practices Principles form the backbone of privacy law in the United States and the concepts they include have played a significant role in the development of data protection laws around the globe. Understanding the Fair Information Practice Principles and how they should be implemented is critical to comply with the various privacy laws that protect personal information.
|
||||
|
||||
In order to be in line with Fair Information Practices we will take the following responsive action, should a data breach occur:
|
||||
|
||||
### We will notify you via email:
|
||||
|
||||
Within 7 business days
|
||||
|
||||
### We will notify the users via in-site notification:
|
||||
|
||||
Within 7 business days
|
||||
We also agree to the Individual Redress Principle which requires that individuals have the right to legally pursue enforceable rights against data collectors and processors who fail to adhere to the law. This principle requires not only that individuals have enforceable rights against data users, but also that individuals have recourse to courts or government agencies to investigate and/or prosecute non-compliance by data processors.
|
||||
|
||||
## CAN SPAM Act
|
||||
|
||||
The CAN-SPAM Act is a law that sets the rules for commercial email, establishes requirements for commercial messages, gives recipients the right to have emails stopped from being sent to them, and spells out tough penalties for violations.
|
||||
|
||||
### We collect your email address in order to:
|
||||
|
||||
Send information, respond to inquiries, and/or other requests or questions
|
||||
Process orders and to send information and updates pertaining to orders.
|
||||
Send you additional information related to your product and/or service
|
||||
Market to our mailing list or continue to send emails to our clients after the original transaction has occurred.
|
||||
To be in accordance with CANSPAM, we agree to the following:
|
||||
|
||||
Not use false or misleading subjects or email addresses.
|
||||
Identify the message as an advertisement in some reasonable way.
|
||||
Include the physical address of our business or site headquarters.
|
||||
Monitor third-party email marketing services for compliance, if one is used.
|
||||
Honor opt-out/unsubscribe requests quickly.
|
||||
Allow users to unsubscribe by using the link at the bottom of each email.
|
||||
If at any time you would like to unsubscribe from receiving future emails, you can email us at: [board@lbry.org](mailto:board@lbry.org)
|
||||
|
||||
Follow the instructions at the bottom of each email.
|
||||
and we will promptly remove you from ALL correspondence.
|
||||
|
||||
## Contacting Us
|
||||
|
||||
If there are any questions regarding this privacy policy, you may contact us using the information below.
|
||||
|
||||
> LBRY Foundation Inc.
|
||||
> 1072 CASITAS PASS RD #122
|
||||
> CARPINTERIA CA 93013
|
||||
> United States
|
||||
> [board@lbry.com](mailto:board@lbry.com)
|
17
package.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@fontsource/roboto": "^4.5.1",
|
||||
"@iconify/json": "^1.1.449",
|
||||
"@iconify/vue2": "^1.1.1",
|
||||
"@vuepress/plugin-pwa": "^1.5.0",
|
||||
"fs-extra": "^9.0.1",
|
||||
"vuepress": "^1.5.0",
|
||||
"vuepress-plugin-sitemap": "^2.3.1",
|
||||
"vuepress-plugin-zooming": "^1.1.7"
|
||||
},
|
||||
"scripts": {
|
||||
"docs:dev": "vuepress dev docs",
|
||||
"docs:build": "vuepress build docs"
|
||||
}
|
||||
}
|