Commit ad4faada authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge branch 'develop' into inphi/op-program-output-root

parents e365a39a 5390cb42
This diff is collapsed.
# Legacy codebases # Packages
/packages/chain-mon @ethereum-optimism/devxpod
/packages/common-ts @ethereum-optimism/typescript-reviewers /packages/common-ts @ethereum-optimism/typescript-reviewers
/packages/contracts @ethereum-optimism/contract-reviewers
/packages/contracts-bedrock @ethereum-optimism/contract-reviewers /packages/contracts-bedrock @ethereum-optimism/contract-reviewers
/packages/core-utils @ethereum-optimism/legacy-reviewers /packages/core-utils @ethereum-optimism/legacy-reviewers
/packages/chain-mon @ethereum-optimism/devxpod
/packages/replica-healthcheck @ethereum-optimism/legacy-reviewers
/packages/sdk @ethereum-optimism/devxpod /packages/sdk @ethereum-optimism/devxpod
/packages/atst @ethereum-optimism/devxpod
# Bedrock codebases # Bedrock codebases
/bedrock-devnet @ethereum-optimism/go-reviewers /bedrock-devnet @ethereum-optimism/go-reviewers
/cannon @ethereum-optimism/go-reviewers /cannon @ethereum-optimism/go-reviewers
/op-batcher @ethereum-optimism/go-reviewers /op-batcher @ethereum-optimism/go-reviewers
/op-bootnode @ethereum-optimism/go-reviewers
/op-chain-ops @ethereum-optimism/go-reviewers /op-chain-ops @ethereum-optimism/go-reviewers
/op-challenger @ethereum-optimism/go-reviewers
/op-e2e @ethereum-optimism/go-reviewers /op-e2e @ethereum-optimism/go-reviewers
/op-exporter @ethereum-optimism/go-reviewers
/op-heartbeat @ethereum-optimism/go-reviewers
/op-node @ethereum-optimism/go-reviewers /op-node @ethereum-optimism/go-reviewers
/op-node/rollup @protolambda @trianglesphere /op-node/rollup @protolambda @trianglesphere
/op-proposer @ethereum-optimism/go-reviewers /op-preimage @ethereum-optimism/go-reviewers
/op-bootnode @ethereum-optimism/go-reviewers
/op-program @ethereum-optimism/go-reviewers /op-program @ethereum-optimism/go-reviewers
/op-proposer @ethereum-optimism/go-reviewers
/op-service @ethereum-optimism/go-reviewers /op-service @ethereum-optimism/go-reviewers
/op-signer @ethereum-optimism/go-reviewers
/op-wheel @ethereum-optimism/go-reviewers
/ops-bedrock @ethereum-optimism/go-reviewers /ops-bedrock @ethereum-optimism/go-reviewers
# Ops # Ops
/.circleci @ethereum-optimism/infra-reviewers /.circleci @ethereum-optimism/infra-reviewers
/.github @ethereum-optimism/infra-reviewers /.github @ethereum-optimism/infra-reviewers
...@@ -37,8 +39,8 @@ ...@@ -37,8 +39,8 @@
/endpoint-monitor @ethereum-optimism/infra-reviewers /endpoint-monitor @ethereum-optimism/infra-reviewers
# Don't add owners if only package.json is updated # Don't add owners if only package.json is updated
/packages/*/package.json /packages/*/package.json
/*/package.json /*/package.json
# JavaScript Releases # JavaScript Releases
/packages/*/CHANGELOG.md @ethereum-optimism/release-managers /packages/*/CHANGELOG.md @ethereum-optimism/release-managers
......
version: 2
updates:
- package-ecosystem: docker
directory: "/ops-bedrock"
schedule:
interval: daily
open-pull-requests-limit: 10
labels:
- dependabot
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
labels:
- dependabot
- package-ecosystem: npm
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
labels:
- dependabot
- package-ecosystem: npm
directory: "/packages/chain-mon"
schedule:
interval: daily
open-pull-requests-limit: 10
labels:
- dependabot
- package-ecosystem: npm
directory: "/packages/core-utils"
schedule:
interval: daily
open-pull-requests-limit: 10
labels:
- dependabot
- package-ecosystem: npm
directory: "/packages/contracts-ts"
schedule:
interval: daily
open-pull-requests-limit: 10
labels:
- dependabot
- package-ecosystem: npm
directory: "/packages/sdk"
schedule:
interval: daily
open-pull-requests-limit: 10
labels:
- dependabot
- package-ecosystem: npm
directory: "/packages/fee-estimation"
schedule:
interval: daily
open-pull-requests-limit: 10
labels:
- dependabot
- package-ecosystem: npm
directory: "/packages/common-ts"
schedule:
interval: daily
open-pull-requests-limit: 10
labels:
- dependabot
- package-ecosystem: gomod
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
labels:
- dependabot
---
C-Protocol-Critical:
- 'packages/contracts-bedrock/**/*.sol'
...@@ -13,18 +13,6 @@ pull_request_rules: ...@@ -13,18 +13,6 @@ pull_request_rules:
- "label!=multiple-reviewers" - "label!=multiple-reviewers"
- "label!=mergify-ignore" - "label!=mergify-ignore"
- "base=develop" - "base=develop"
- or:
- and:
- "label!=SR-Risk"
- "label!=C-Protocol-Critical"
- and:
- "label=SR-Risk"
- "approved-reviews-by=maurelian"
- and:
- "label=C-Protocol-Critical"
- or:
- "approved-reviews-by=tynes"
- "approved-reviews-by=smartcontracts"
actions: actions:
queue: queue:
name: default name: default
...@@ -47,28 +35,6 @@ pull_request_rules: ...@@ -47,28 +35,6 @@ pull_request_rules:
label: label:
remove: remove:
- on-merge-train - on-merge-train
- name: Handle security critical PRs
conditions:
- "label=SR-Risk"
actions:
request_reviews:
users:
- "maurelian"
comment:
message: |
Hey there @{{author}}! You flagged this PR as security critical. To make review easier, please add a comment describing
1. The risks present in this PR.
2. The mitigations you have added to try and reduce those risks.
- name: Request protocol critical reviewers
conditions:
- label=C-Protocol-Critical
actions:
request_reviews:
users:
- tynes
- smartcontracts
random_count: 1
- name: Ask to resolve conflict - name: Ask to resolve conflict
conditions: conditions:
- conflict - conflict
......
---
name: "Pull Request Labeler"
on:
- pull_request_target
jobs:
pr-labeler:
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@main
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
configuration-path: .github/labeler.yml
...@@ -19,7 +19,7 @@ jobs: ...@@ -19,7 +19,7 @@ jobs:
balance-mon: ${{ steps.packages.outputs.balance-mon }} balance-mon: ${{ steps.packages.outputs.balance-mon }}
drippie-mon: ${{ steps.packages.outputs.drippie-mon }} drippie-mon: ${{ steps.packages.outputs.drippie-mon }}
wd-mon: ${{ steps.packages.outputs.wd-mon }} wd-mon: ${{ steps.packages.outputs.wd-mon }}
replica-healthcheck: ${{ steps.packages.outputs.replica-healthcheck }} replica-mon: ${{ steps.packages.outputs.replica-mon }}
canary-docker-tag: ${{ steps.docker-image-name.outputs.canary-docker-tag }} canary-docker-tag: ${{ steps.docker-image-name.outputs.canary-docker-tag }}
op-exporter: ${{ steps.packages.outputs.op-exporter }} op-exporter: ${{ steps.packages.outputs.op-exporter }}
endpoint-monitor: ${{ steps.packages.outputs.endpoint-monitor }} endpoint-monitor: ${{ steps.packages.outputs.endpoint-monitor }}
...@@ -151,10 +151,10 @@ jobs: ...@@ -151,10 +151,10 @@ jobs:
push: true push: true
tags: ethereumoptimism/wd-mon:${{ needs.canary-publish.outputs.canary-docker-tag }} tags: ethereumoptimism/wd-mon:${{ needs.canary-publish.outputs.canary-docker-tag }}
replica-healthcheck: replica-mon:
name: Publish Replica Healthcheck Version ${{ needs.canary-publish.outputs.canary-docker-tag }} name: Publish replica-mon Version ${{ needs.canary-publish.outputs.canary-docker-tag }}
needs: canary-publish needs: canary-publish
if: needs.canary-publish.outputs.replica-healthcheck != '' if: needs.canary-publish.outputs.replica-mon != ''
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
...@@ -174,9 +174,9 @@ jobs: ...@@ -174,9 +174,9 @@ jobs:
with: with:
context: . context: .
file: ./ops/docker/Dockerfile.packages file: ./ops/docker/Dockerfile.packages
target: replica-healthcheck target: replica-mon
push: true push: true
tags: ethereumoptimism/replica-healthcheck:${{ needs.canary-publish.outputs.canary-docker-tag }} tags: ethereumoptimism/replica-mon:${{ needs.canary-publish.outputs.canary-docker-tag }}
op-exporter: op-exporter:
name: Publish op-exporter Version ${{ needs.canary-publish.outputs.canary-docker-tag }} name: Publish op-exporter Version ${{ needs.canary-publish.outputs.canary-docker-tag }}
......
...@@ -20,7 +20,7 @@ jobs: ...@@ -20,7 +20,7 @@ jobs:
balance-mon: ${{ steps.packages.outputs.drippie-mon }} balance-mon: ${{ steps.packages.outputs.drippie-mon }}
drippie-mon: ${{ steps.packages.outputs.drippie-mon }} drippie-mon: ${{ steps.packages.outputs.drippie-mon }}
wd-mon: ${{ steps.packages.outputs.wd-mon }} wd-mon: ${{ steps.packages.outputs.wd-mon }}
replica-healthcheck: ${{ steps.packages.outputs.replica-healthcheck }} replica-mon: ${{ steps.packages.outputs.replica-mon }}
op-exporter: ${{ steps.packages.outputs.op-exporter }} op-exporter: ${{ steps.packages.outputs.op-exporter }}
endpoint-monitor: ${{ steps.packages.outputs.endpoint-monitor }} endpoint-monitor: ${{ steps.packages.outputs.endpoint-monitor }}
# Permissions necessary for Changesets to push a new branch and open PRs # Permissions necessary for Changesets to push a new branch and open PRs
...@@ -41,6 +41,11 @@ jobs: ...@@ -41,6 +41,11 @@ jobs:
- name: Setup - name: Setup
uses: ./.github/actions/setup uses: ./.github/actions/setup
- name: Set deployment token
run: npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}"
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
# Makes a pr to publish the changesets that when # Makes a pr to publish the changesets that when
# merged will publish to npm # merged will publish to npm
# see https://github.com/changesets/action # see https://github.com/changesets/action
...@@ -208,10 +213,10 @@ jobs: ...@@ -208,10 +213,10 @@ jobs:
push: true push: true
tags: ethereumoptimism/drippie-mon:${{ needs.release.outputs.drippie-mon }},ethereumoptimism/drippie-mon:latest tags: ethereumoptimism/drippie-mon:${{ needs.release.outputs.drippie-mon }},ethereumoptimism/drippie-mon:latest
replica-healthcheck: replica-mon:
name: Publish Replica Healthcheck Version ${{ needs.release.outputs.replica-healthcheck }} name: Publish Replica Healthcheck Version ${{ needs.release.outputs.replica-mon }}
needs: release needs: release
if: needs.release.outputs.replica-healthcheck != '' if: needs.release.outputs.replica-mon != ''
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
...@@ -231,9 +236,9 @@ jobs: ...@@ -231,9 +236,9 @@ jobs:
with: with:
context: . context: .
file: ./ops/docker/Dockerfile.packages file: ./ops/docker/Dockerfile.packages
target: replica-healthcheck target: replica-mon
push: true push: true
tags: ethereumoptimism/replica-healthcheck:${{ needs.release.outputs.replica-healthcheck }},ethereumoptimism/replica-healthcheck:latest tags: ethereumoptimism/replica-mon:${{ needs.release.outputs.replica-mon }},ethereumoptimism/replica-mon:latest
endpoint-monitor: endpoint-monitor:
name: Publish endpoint-monitor Version ${{ needs.release.outputs.endpoint-monitor}} name: Publish endpoint-monitor Version ${{ needs.release.outputs.endpoint-monitor}}
......
[submodule "packages/contracts-bedrock/lib/openzeppelin-contracts-upgradeable"]
path = packages/contracts-bedrock/lib/openzeppelin-contracts-upgradeable
url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable
[submodule "packages/contracts-bedrock/lib/openzeppelin-contracts"]
path = packages/contracts-bedrock/lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
[submodule "packages/contracts-bedrock/lib/solmate"]
path = packages/contracts-bedrock/lib/solmate
url = https://github.com/transmissions11/solmate
[submodule "packages/contracts-bedrock/lib/clones-with-immutable-args"]
path = packages/contracts-bedrock/lib/clones-with-immutable-args
url = https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args
[submodule "packages/contracts-bedrock/lib/ds-test"]
path = packages/contracts-bedrock/lib/ds-test
url = https://github.com/dapphub/ds-test
[submodule "packages/contracts-bedrock/lib/forge-std"]
path = packages/contracts-bedrock/lib/forge-std
url = https://github.com/foundry-rs/forge-std
...@@ -25,4 +25,4 @@ ...@@ -25,4 +25,4 @@
"eslint.format.enable": true, "eslint.format.enable": true,
"editorconfig.generateAuto": false, "editorconfig.generateAuto": false,
"files.trimTrailingWhitespace": true "files.trimTrailingWhitespace": true
} }
\ No newline at end of file
...@@ -54,7 +54,6 @@ Refer to the Directory Structure section below to understand which packages are ...@@ -54,7 +54,6 @@ Refer to the Directory Structure section below to understand which packages are
│ ├── <a href="./packages/contracts-bedrock">contracts-bedrock</a>: Bedrock smart contracts. │ ├── <a href="./packages/contracts-bedrock">contracts-bedrock</a>: Bedrock smart contracts.
│ ├── <a href="./packages/core-utils">core-utils</a>: Low-level utilities that make building Optimism easier │ ├── <a href="./packages/core-utils">core-utils</a>: Low-level utilities that make building Optimism easier
│ ├── <a href="./packages/chain-mon">chain-mon</a>: Chain monitoring services │ ├── <a href="./packages/chain-mon">chain-mon</a>: Chain monitoring services
│ ├── <a href="./packages/replica-healthcheck">replica-healthcheck</a>: Service for monitoring the health of a replica node
│ └── <a href="./packages/sdk">sdk</a>: provides a set of tools for interacting with Optimism │ └── <a href="./packages/sdk">sdk</a>: provides a set of tools for interacting with Optimism
├── <a href="./op-bindings">op-bindings</a>: Go bindings for Bedrock smart contracts. ├── <a href="./op-bindings">op-bindings</a>: Go bindings for Bedrock smart contracts.
├── <a href="./op-batcher">op-batcher</a>: L2-Batch Submitter, submits bundles of batches to L1 ├── <a href="./op-batcher">op-batcher</a>: L2-Batch Submitter, submits bundles of batches to L1
...@@ -79,7 +78,6 @@ Refer to the Directory Structure section below to understand which packages are ...@@ -79,7 +78,6 @@ Refer to the Directory Structure section below to understand which packages are
│ ├── <a href="./packages/common-ts">common-ts</a>: Common tools for building apps in TypeScript │ ├── <a href="./packages/common-ts">common-ts</a>: Common tools for building apps in TypeScript
│ ├── <a href="./packages/core-utils">core-utils</a>: Low-level utilities that make building Optimism easier │ ├── <a href="./packages/core-utils">core-utils</a>: Low-level utilities that make building Optimism easier
│ ├── <a href="./packages/chain-mon">chain-mon</a>: Chain monitoring services │ ├── <a href="./packages/chain-mon">chain-mon</a>: Chain monitoring services
│ ├── <a href="./packages/replica-healthcheck">replica-healthcheck</a>: Service for monitoring the health of a replica node
│ └── <a href="./packages/sdk">sdk</a>: provides a set of tools for interacting with Optimism │ └── <a href="./packages/sdk">sdk</a>: provides a set of tools for interacting with Optimism
├── <a href="./indexer">indexer</a>: indexes and syncs transactions ├── <a href="./indexer">indexer</a>: indexes and syncs transactions
├── <a href="./op-exporter">op-exporter</a>: A prometheus exporter to collect/serve metrics from an Optimism node ├── <a href="./op-exporter">op-exporter</a>: A prometheus exporter to collect/serve metrics from an Optimism node
......
...@@ -23,8 +23,20 @@ test: elf ...@@ -23,8 +23,20 @@ test: elf
lint: lint:
golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 5m -e "errors.As" -e "errors.Is" golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 5m -e "errors.As" -e "errors.Is"
fuzz:
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateSyscallBrk ./mipsevm
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateSyscallClone ./mipsevm
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateSyscallMmap ./mipsevm
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateSyscallExitGroup ./mipsevm
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateSyscallFnctl ./mipsevm
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateHintRead ./mipsevm
go test -run NOTAREALTEST -v -fuzztime 20s -fuzz=FuzzStatePreimageRead ./mipsevm
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateHintWrite ./mipsevm
go test -run NOTAREALTEST -v -fuzztime 20s -fuzz=FuzzStatePreimageWrite ./mipsevm
.PHONY: \ .PHONY: \
cannon \ cannon \
clean \ clean \
test \ test \
lint lint \
fuzz
This diff is collapsed.
This diff is collapsed.
...@@ -6,6 +6,16 @@ import ( ...@@ -6,6 +6,16 @@ import (
"io" "io"
) )
const (
sysMmap = 4090
sysBrk = 4045
sysClone = 4120
sysExitGroup = 4246
sysRead = 4003
sysWrite = 4004
sysFcntl = 4055
)
func (m *InstrumentedState) readPreimage(key [32]byte, offset uint32) (dat [32]byte, datLen uint32) { func (m *InstrumentedState) readPreimage(key [32]byte, offset uint32) (dat [32]byte, datLen uint32) {
preimage := m.lastPreimage preimage := m.lastPreimage
if key != m.lastPreimageKey { if key != m.lastPreimageKey {
...@@ -43,7 +53,7 @@ func (m *InstrumentedState) handleSyscall() error { ...@@ -43,7 +53,7 @@ func (m *InstrumentedState) handleSyscall() error {
//fmt.Printf("syscall: %d\n", syscallNum) //fmt.Printf("syscall: %d\n", syscallNum)
switch syscallNum { switch syscallNum {
case 4090: // mmap case sysMmap:
sz := a1 sz := a1
if sz&PageAddrMask != 0 { // adjust size to align with page size if sz&PageAddrMask != 0 { // adjust size to align with page size
sz += PageSize - (sz & PageAddrMask) sz += PageSize - (sz & PageAddrMask)
...@@ -56,15 +66,15 @@ func (m *InstrumentedState) handleSyscall() error { ...@@ -56,15 +66,15 @@ func (m *InstrumentedState) handleSyscall() error {
v0 = a0 v0 = a0
//fmt.Printf("mmap hint 0x%x size 0x%x\n", v0, sz) //fmt.Printf("mmap hint 0x%x size 0x%x\n", v0, sz)
} }
case 4045: // brk case sysBrk:
v0 = 0x40000000 v0 = 0x40000000
case 4120: // clone (not supported) case sysClone: // clone (not supported)
v0 = 1 v0 = 1
case 4246: // exit_group case sysExitGroup:
m.state.Exited = true m.state.Exited = true
m.state.ExitCode = uint8(a0) m.state.ExitCode = uint8(a0)
return nil return nil
case 4003: // read case sysRead:
// args: a0 = fd, a1 = addr, a2 = count // args: a0 = fd, a1 = addr, a2 = count
// returns: v0 = read, v1 = err code // returns: v0 = read, v1 = err code
switch a0 { switch a0 {
...@@ -98,7 +108,7 @@ func (m *InstrumentedState) handleSyscall() error { ...@@ -98,7 +108,7 @@ func (m *InstrumentedState) handleSyscall() error {
v0 = 0xFFffFFff v0 = 0xFFffFFff
v1 = MipsEBADF v1 = MipsEBADF
} }
case 4004: // write case sysWrite:
// args: a0 = fd, a1 = addr, a2 = count // args: a0 = fd, a1 = addr, a2 = count
// returns: v0 = written, v1 = err code // returns: v0 = written, v1 = err code
switch a0 { switch a0 {
...@@ -144,7 +154,7 @@ func (m *InstrumentedState) handleSyscall() error { ...@@ -144,7 +154,7 @@ func (m *InstrumentedState) handleSyscall() error {
v0 = 0xFFffFFff v0 = 0xFFffFFff
v1 = MipsEBADF v1 = MipsEBADF
} }
case 4055: // fcntl case sysFcntl:
// args: a0 = fd, a1 = cmd // args: a0 = fd, a1 = cmd
if a1 == 3 { // F_GETFL: get file descriptor flags if a1 == 3 { // F_GETFL: get file descriptor flags
switch a0 { switch a0 {
......
...@@ -36,5 +36,4 @@ flag_management: ...@@ -36,5 +36,4 @@ flag_management:
- name: core-utils-tests - name: core-utils-tests
- name: dtl-tests - name: dtl-tests
- name: chain-mon-tests - name: chain-mon-tests
- name: replica-healthcheck-tests
- name: sdk-tests - name: sdk-tests
# The OP Stack Docs
[![Discord](https://img.shields.io/discord/667044843901681675.svg?color=768AD4&label=discord&logo=https%3A%2F%2Fdiscordapp.com%2Fassets%2F8c9701b98ad4372b58f13fd9f65f966e.svg)](https://discord.gg/optimism)
[![Twitter Follow](https://img.shields.io/twitter/follow/optimismPBC.svg?label=optimismPBC&style=social)](https://twitter.com/optimismPBC)
The OP Stack is an open, collectively maintained development stack for blockchain ecosystems.
This repository contains the source code for the [OP Stack Docs](https://stack.optimism.io).
## Development
### Serving docs locally
```sh
yarn dev
```
Then navigate to [http://localhost:8080](http://localhost:8080).
If that link doesn't work, double check the output of `yarn dev`.
You might already be serving something on port 8080 and the site may be on another port (e.g., 8081).
### Building docs for production
```sh
yarn build
```
You probably don't need to run this command, but now you know.
### Editing docs
Edit the markdown directly in [src/docs](./src/docs).
### Adding new docs
Add your markdown files to [src/docs](./src/docs).
You will also have to update [src/.vuepress/config.js](./src/.vuepress/config.js) if you want these docs to show up in the sidebar.
### Updating the theme
We currently use an ejected version of [vuepress-theme-hope](https://vuepress-theme-hope.github.io/).
Since the version we use was ejected from the original theme, you'll see a bunch of compiled JavaScript files instead of the original TypeScript files.
There's not much we can do about that right now, so you'll just need to make do and edit the raw JS if you need to make theme adjustments.
We're planning to move away from VuePress relatively soon anyway so we won't be fixing this.
{
"name": "@eth-optimism/op-stack-docs",
"version": "0.0.2",
"description": "The OP Stack Docs",
"main": "index.js",
"scripts": {
"dev": "vuepress dev src",
"build": "vuepress build src",
"preview": "yarn build && serve -s src/.vuepress/dist -p 8080"
},
"license": "MIT",
"devDependencies": {
"@vuepress/plugin-medium-zoom": "^1.8.2",
"@vuepress/plugin-pwa": "^1.9.7",
"serve": "^14.2.0",
"vuepress": "^1.8.2",
"vuepress-plugin-plausible-analytics": "^0.2.1",
"vuepress-theme-hope": "^1.22.0"
},
"dependencies": {
"check-md": "^1.0.2",
"dayjs": "^1.11.7"
}
}
const { description } = require('../../package')
const path = require('path')
module.exports = {
title: 'OP Stack Docs',
description: description,
head: [
['link', { rel: 'manifest', href: '/manifest.json' }],
['meta', { name: 'theme-color', content: '#3eaf7c' }],
['meta', { name: 'apple-mobile-web-app-capable', content: 'yes' }],
['meta', { name: 'apple-mobile-web-app-status-bar-style', content: 'black' }],
['meta', { property: 'og:image', content: 'https://stack.optimism.io/assets/logos/twitter-logo.png' }],
['meta', { name: 'twitter:image', content: 'https://stack.optimism.io/assets/logos/twitter-logo.png' }],
['meta', { name: 'twitter:title', content: 'OP Stack Docs' }],
['meta', { property: 'og:title', content: 'OP Stack Docs' }],
['meta', { name: 'twitter:card', content: 'summary' } ],
['link', { rel: "icon", type: "image/png", sizes: "32x32", href: "/assets/logos/favicon.png"}],
],
theme: path.resolve(__dirname, './theme'),
themeConfig: {
"twitter:card": "summary",
contributor: false,
hostname: 'https://stack.optimism.io',
logo: '/assets/logos/logo.png',
docsDir: 'src',
docsRepo: 'https://github.com/ethereum-optimism/opstack-docs',
docsBranch: 'main',
lastUpdated: false,
darkmode: 'disable',
themeColor: false,
blog: false,
iconPrefix: 'far fa-',
pageInfo: false,
pwa: {
cacheHTML: false,
},
activeHash: {
offset: -200,
},
algolia: {
appId: 'O9WKE9RMCV',
apiKey: '00cf17cba30b374d08d7f7afead974be',
indexName: 'optimism'
},
nav: [
{
text: 'Home',
link: 'https://www.optimism.io/'
},
{
text: 'OP Stack Docs',
link: '/'
},
{
text: 'Optimism Docs',
link: 'https://community.optimism.io/'
},
{
text: 'Governance',
link: 'https://community.optimism.io/docs/governance/'
},
{
text: 'Community',
items: [
{
icon: 'discord',
iconPrefix: 'fab fa-',
iconClass: 'color-discord',
text: 'Discord',
link: 'https://discord.optimism.io',
},
{
icon: 'github',
iconPrefix: 'fab fa-',
iconClass: 'color-github',
text: 'GitHub',
link: 'https://github.com/ethereum-optimism/optimism',
},
{
icon: 'twitter',
iconPrefix: 'fab fa-',
iconClass: 'color-twitter',
text: 'Twitter',
link: 'https://twitter.com/optimismFND',
},
{
icon: 'twitch',
iconPrefix: 'fab fa-',
iconClass: 'color-twitch',
text: 'Twitch',
link: 'https://www.twitch.tv/optimismpbc'
},
{
icon: 'medium',
iconPrefix: 'fab fa-',
iconClass: 'color-medium',
text: 'Blog',
link: 'https://optimismpbc.medium.com/'
},
{
icon: 'computer-classic',
iconClass: 'color-ecosystem',
text: 'Ecosystem',
link: 'https://www.optimism.io/apps/all',
},
{
icon: 'globe',
iconClass: 'color-optimism',
text: 'optimism.io',
link: 'https://www.optimism.io/',
}
]
}
],
searchPlaceholder: 'Search the docs',
sidebar: [
{
title: "OP Stack",
collapsable: false,
children: [
'/',
[
'/docs/understand/design-principles.md',
'Design Principles'
],
'/docs/understand/landscape.md',
'/docs/understand/explainer.md'
]
},
{
title: "Releases",
collapsable: false,
children: [
'/docs/releases/',
{
title: "Bedrock",
collapsable: true,
children: [
'/docs/releases/bedrock/',
'/docs/releases/bedrock/explainer.md',
'/docs/releases/bedrock/differences.md'
]
}
]
},
{
title: "Building OP Stack Rollups",
collapsable: false,
children: [
'/docs/build/getting-started.md',
'/docs/build/conf.md',
'/docs/build/operations.md',
'/docs/build/explorer.md',
'/docs/build/sdk.md',
{
title: "OP Stack Hacks",
collapsable: true,
children: [
'/docs/build/hacks.md',
'/docs/build/featured.md',
'/docs/build/data-avail.md',
'/docs/build/derivation.md',
'/docs/build/execution.md',
'/docs/build/settlement.md',
{
title: "Sample Hacks",
children: [
"/docs/build/tutorials/add-attr.md",
"/docs/build/tutorials/new-precomp.md",
"/docs/build/tutorials/predeploys.md"
]
} // End of tutorials
],
}, // End of OP Stack hacks
],
}, // End of Building OP Stack Rollups
{
title: "Contributing",
collapsable: false,
children: [
'/docs/contribute.md',
]
},
{
title: "Security",
collapsable: false,
children: [
'/docs/security/faq.md',
'/docs/security/policy.md',
'/docs/security/pause.md',
'/docs/security/forced-withdrawal.md',
]
},
], // end of sidebar
plugins: [
"@vuepress/pwa",
[
'@vuepress/plugin-medium-zoom',
{
selector: ':not(a) > img'
}
],
"plausible-analytics"
]
}
}
// module.exports.themeConfig.sidebar["/docs/useful-tools/"] = module.exports.themeConfig.sidebar["/docs/developers/"]
import event from '@vuepress/plugin-pwa/lib/event'
export default ({ router }) => {
registerAutoReload();
router.addRoutes([
{ path: '/docs/', redirect: '/' },
])
}
// When new content is detected by the app, this will automatically
// refresh the page, so that users do not need to manually click
// the refresh button. For more details see:
// https://linear.app/optimism/issue/FE-1003/investigate-archive-issue-on-docs
const registerAutoReload = () => {
event.$on('sw-updated', e => {
e.skipWaiting().then(() =>
{
if (typeof location !== 'undefined')
location.reload(true);
}
)
})
}
{
"name": "OP Docs",
"short_name": "OP Docs",
"description": "The official OP Docs",
"icons": [
{
"src": "/assets/logos/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/assets/logos/icon-256x256.png",
"sizes": "256x256",
"type": "image/png"
},
{
"src": "/assets/logos/icon-384x384.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "/assets/logos/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "/assets/logos/icon-1020x1020.png",
"sizes": "any",
"type": "image/png"
}
],
"start_url": "/index.html",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#ff0420"
}
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Rubik:ital,wght@0,400;0,600;0,700;1,600;1,700&display=swap');
@import 'https://pro.fontawesome.com/releases/v5.15.4/css/all.css';
main, body, html {
font-family: 'Open Sans', sans-serif;
}
p {
font-size: 16px;
line-height: 24px;
}
aside.sidebar {
background-color: #F1F4F9;
border-right: none;
}
p.sidebar-heading {
color: #323A43 !important;
font-family: 'Open Sans', sans-serif;
font-weight: 600 !important;
font-size: 14px !important;
line-height: 24px !important;
min-height: 36px;
margin-left: 20px;
padding: 8px 16px !important;
width: calc(100% - 60px) !important;
border-radius: 8px;
}
a.sidebar-link {
font-family: 'Open Sans', sans-serif;
font-size: 14px !important;
line-height: 24px !important;
min-height: 36px;
margin-top: 3px;
margin-left: 20px;
padding: 8px 16px !important;
width: calc(100% - 60px) !important;
border-radius: 8px;
}
section.sidebar-group a.sidebar-link,
section.sidebar-group p.sidebar-heading.clickable {
margin-left: 32px;
width: calc(100% - 60px) !important;
}
.sidebar-links:not(.sidebar-group-items) > li > a.sidebar-link {
font-weight: 600 !important;
color: #323A43 !important;
}
.sidebar-links:not(.sidebar-group-items) > li > a.sidebar-link.active {
border-left-color: #F1F4F9 !important;
background-color: #FFDBDF !important;
color: #FF0420 !important;
}
a.sidebar-link.active {
border-left-color: #F1F4F9 !important;
background-color: #FFDBDF !important;
color: #FF0420 !important;
}
h1 {
font-size: 50px;
}
h2 {
font-size: 40px;
}
h3 {
font-size: 28px;
}
h4 {
font-size: 20px;
}
h1 {
font-family: 'Rubik', sans-serif;
font-weight: 700;
font-style: italic;
border-bottom: none;
color: #202327 !important;
}
h2, h3, h4 {
font-family: 'Rubik', sans-serif;
border-bottom: none;
font-weight: 400;
}
#search-form {
@media (min-width $MQNormal) {
margin-left: 2rem;
}
}
.search-box {
@media (min-width $MQNormal) {
order: 1;
margin-right: 0;
margin-left: 1rem;
.suggestions {
left: auto !important;
right: 0 !important;
}
}
input {
border-color: #CBD5E0 !important;
border-radius: 100px !important;
background-color: #FFFFFF !important;
}
}
header.navbar {
border-bottom: none;
box-shadow: 0px 6px 8px -6px rgba(20, 23, 26, 0.06), 0px 8px 16px -6px rgba(20, 23, 26, 0.04);
--bgcolor-blur: hsla(0,0%,100%,0.9);
}
span.site-name {
display: none !important;
}
a.nav-link,
div.nav-item span.title {
font-weight: 600;
}
a.nav-link:not(.router-link-active),
div.nav-item span.title {
color: #68778D;
}
.theme-default-content:not(.custom) > p {
text-align: inherit !important;
}
.sidebar {
box-shadow: none !important;
}
div.hero-info {
color: white;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
}
div.hero-info .description {
display: none;
}
div.hero-info #main-title {
color: white !important;
}
header.hero > img {
border-radius: 16px;
max-height: none !important;
}
header.hero {
margin-top: 20px;
position: relative;
justify-content: space-between !important;
}
.home .features {
border-top: none !important;
justify-content: space-between !important;
margin: 0 !important;
padding-top: 0.5rem !important;
}
.home .features h2 {
font-family: 'Open Sans', sans-serif;
font-style: normal;
font-size: 16px !important;
font-weight: 600 !important;
color: #202327 !important;
}
.home .features p {
font-family: 'Open Sans', sans-serif;
font-size: 14px !important;
color: #68778D !important;
}
.home .features .icon-container {
height: 44px;
width: 44px;
background-color: #FFF0F1;
border-radius: 8px;
display: flex;
justify-content: center;
align-items: center;
color: #FF0420;
}
.home .features .feature {
background-color: #FFFFFF !important;
box-shadow: 0px 6px 8px -6px rgba(20, 23, 26, 0.12), 0px 8px 16px -6px rgba(20, 23, 26, 0.08);
border-radius: 16px !important;
margin: 0 !important;
margin-bottom: 2rem !important;
padding: 1.5rem !important;
}
.features-header {
margin-top: 30px;
margin-bottom: 0px;
}
div.theme-container:not(.has-sidebar) {
background-color: #F1F4F9;
}
.anchor-header {
color: #202327;
font-weight: 600;
font-size: 14px;
font-height: 20px;
margin-bottom: 10px;
}
.anchor-support {
margin-top: 20px;
}
.anchor-support-links i {
width: 20px;
text-align: center;
margin-right: 5px;
}
.anchor-support-links a {
color: #68778D;
}
.anchor-support-links a div {
height: 30px;
font-size: 14px;
}
.anchor-support-links a:hover {
color: #FF0420;
}
#anchor {
width: 15rem !important;
}
#anchor .anchor {
line-height: 27.2px !important;
}
#anchor .anchor div {
color: #68778D !important;
}
#anchor .anchor.active div {
font-weight: 600 !important;
}
.theme-default-content code {
top: 1px;
line-height: 22.4px !important;
vertical-align: middle !important;
}
.nav-dropdown svg.icon.outbound {
display: none;
}
.nav-dropdown .dropdown-item i {
width: 20px;
}
.color-discord {
color: #5865F2;
}
.color-github {
color: #121212;
}
.color-twitter {
color: #1DA1F2;
}
.color-twitch {
color: #6441A5;
}
.color-medium {
color: #000000;
}
.color-optimism {
color: #FF0420;
}
.color-ecosystem {
color: #ea94db;
}
$textColor = #000000
$accentColor = #f01a37
$backgroundColor = #272934
$lightBackgroundColor = #f3f3f3
$sidebarWidth = 320px
import Vue from "vue";
import type { AlgoliaOption } from "@mr-hope/vuepress-types";
declare const _default: import("vue/types/vue").ExtendedVue<Vue, {
placeholder: string;
}, {
initialize(userOptions: AlgoliaOption, lang: string): void;
update(options: AlgoliaOption, lang: string): void;
}, unknown, {
options: AlgoliaOption;
}>;
export default _default;
import Vue from "vue";
export default Vue.extend({
name: "AlgoliaSearchDropdown",
props: {
options: { type: Object, required: true },
},
data: () => ({
placeholder: "",
}),
watch: {
$lang(newValue) {
this.update(this.options, newValue);
},
options(newValue) {
this.update(newValue, this.$lang);
},
},
mounted() {
this.initialize(this.options, this.$lang);
this.placeholder =
this.$site.themeConfig.searchPlaceholder || "";
},
methods: {
initialize(userOptions, lang) {
void Promise.all([
import(
/* webpackChunkName: "docsearch" */ "docsearch.js/dist/cdn/docsearch.min.js"),
import(
/* webpackChunkName: "docsearch" */ "docsearch.js/dist/cdn/docsearch.min.css"),
]).then(([docsearch]) => {
// eslint-disable-next-line
docsearch.default(Object.assign(Object.assign({}, userOptions), { inputSelector: "#algolia-search-input",
// #697 Make docsearch work well at i18n mode.
algoliaOptions: {
facetFilters: [`lang:${lang}`].concat(
// eslint-disable-next-line
userOptions.facetFilters || []),
}, handleSelected: (_input, _event, suggestion) => {
const { pathname, hash } = new URL(suggestion.url);
const routepath = pathname.replace(this.$site.base, "/");
if (this.$router.getRoutes().some((route) => route.path === routepath))
void this.$router.push(`${routepath}${decodeURIComponent(hash)}`);
else
window.open(suggestion.url);
} }));
});
},
update(options, lang) {
this.$el.innerHTML =
'<input id="algolia-search-input" class="search-query">';
this.initialize(options, lang);
},
},
});
//# sourceMappingURL=Dropdown.js.map
\ No newline at end of file
{"version":3,"file":"Dropdown.js","sourceRoot":"","sources":["Dropdown.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AAKtB,eAAe,GAAG,CAAC,MAAM,CAAC;IACxB,IAAI,EAAE,uBAAuB;IAE7B,KAAK,EAAE;QACL,OAAO,EAAE,EAAE,IAAI,EAAE,MAAiC,EAAE,QAAQ,EAAE,IAAI,EAAE;KACrE;IAED,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QACX,WAAW,EAAE,EAAE;KAChB,CAAC;IAEF,KAAK,EAAE;QACL,KAAK,CAAC,QAAgB;YACpB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACtC,CAAC;QAED,OAAO,CAAC,QAAuB;YAC7B,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACpC,CAAC;KACF;IAED,OAAO;QACL,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,CAAC,WAAW;YACb,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,iBAA4B,IAAI,EAAE,CAAC;IAC/D,CAAC;IAED,OAAO,EAAE;QACP,UAAU,CAAC,WAA0B,EAAE,IAAY;YACjD,KAAK,OAAO,CAAC,GAAG,CAAC;gBACf,MAAM;gBACJ,mCAAmC,CAAC,wCAAwC,CAC7E;gBACD,MAAM;gBACJ,mCAAmC,CAAC,yCAAyC,CAC9E;aACF,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE;gBACtB,2BAA2B;gBAC1B,SAAiB,CAAC,OAAO,iCACrB,WAAW,KACd,aAAa,EAAE,uBAAuB;oBACtC,8CAA8C;oBAC9C,cAAc,EAAE;wBACd,YAAY,EAAE,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,MAAM;wBACnC,2BAA2B;wBACzB,WAAmB,CAAC,YAAyB,IAAI,EAAE,CACtD;qBACF,EACD,cAAc,EAAE,CACd,MAAwB,EACxB,MAAa,EACb,UAA2B,EAC3B,EAAE;wBACF,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;wBACnD,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;wBAEzD,IACE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC;4BAElE,KAAK,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,SAAS,GAAG,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;;4BAC/D,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;oBACnC,CAAC,IACD,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;QAED,MAAM,CAAC,OAAsB,EAAE,IAAY;YACzC,IAAI,CAAC,GAAG,CAAC,SAAS;gBAChB,wDAAwD,CAAC;YAC3D,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACjC,CAAC;KACF;CACF,CAAC,CAAC"}
\ No newline at end of file
<template>
<form
id="search-form"
class="algolia-search-wrapper search-box"
role="search"
>
<label class="sr-only" for="algolia-search-input">Algolia search</label>
<input
id="algolia-search-input"
class="search-query"
:placeholder="placeholder"
/>
</form>
</template>
<script src="./Dropdown" />
<style lang="stylus">
.algolia-search-wrapper
& > span
vertical-align middle
.algolia-autocomplete
line-height normal
.ds-dropdown-menu
min-width 515px !important
margin 6px 0 0
padding 4px
border 1px solid var(--light-grey)
border-radius 4px
background var(--bgcolor)
font-size 16px
text-align left
@media (max-width $MQMobile)
min-width calc(100vw - 4rem) !important
max-width calc(100vw - 4rem) !important
&:before
border-color var(--light-grey)
[class*=ds-dataset-]
padding 0
border none
background var(--bgcolor)
.ds-suggestions
margin-top 0
.ds-suggestion
border-bottom 1px solid var(--border-color)
.algolia-docsearch-suggestion--highlight
color var(--accent-color)
.algolia-docsearch-suggestion
padding 0
border-color var(--border-color)
background var(--bgcolor)
color var(--text-color)
.algolia-docsearch-suggestion--category-header
padding 5px 10px
margin-top 0
background var(--accent-color)
color var(--white)
font-weight 600
.algolia-docsearch-suggestion--highlight
background rgba(255, 255, 255, 0.6)
.algolia-docsearch-suggestion--wrapper
padding 0
@media (max-width $MQMobile)
padding 5px 7px 5px 5px !important
.algolia-docsearch-suggestion--title
margin-bottom 0
color var(--text-color)
font-weight 600
.algolia-docsearch-suggestion--subcategory-column
vertical-align top
padding 5px 7px 5px 5px
border-color var(--border-color)
background var(--bgcolor)
color var(--text-color)
@media (min-width $MQMobile)
display table-cell
float none
width 150px
min-width 150px
@media (max-width $MQMobile)
padding 0 !important
background white !important
&:after
display none
.algolia-docsearch-suggestion--subcategory-column-text
color #555
&:after
@media (max-width $MQMobile)
display inline-block
vertical-align middle
content ' > '
width 5px
margin -3px 3px 0
font-size 10px
line-height 14.4px
.algolia-docsearch-suggestion--content
@media (min-width $MQMobile)
display table-cell
float none
vertical-align top
width 100%
.algolia-docsearch-footer
border-color var(--border-color)
.ds-cursor .algolia-docsearch-suggestion--content
background var(--grey3)
color var(--text-color)
</style>
import Vue from "vue";
import type { AlgoliaOption } from "@mr-hope/vuepress-types";
declare const _default: import("vue/types/vue").ExtendedVue<Vue, unknown, {
initialize(userOptions: AlgoliaOption, _lang: string): void;
resolveRoutePathFromUrl(absoluteUrl: string): string;
update(options: AlgoliaOption, lang: string): void;
}, unknown, {
options: AlgoliaOption;
}>;
export default _default;
import { createElement } from "preact";
import Vue from "vue";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: docsearch type issue
import docsearch from "@docsearch/js";
export default Vue.extend({
name: "AlgoliaSearchFull",
props: {
options: { type: Object, required: true },
},
watch: {
$lang(newValue) {
this.update(this.options, newValue);
},
options(newValue) {
this.update(newValue, this.$lang);
},
},
mounted() {
this.initialize(this.options, this.$lang);
},
methods: {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
initialize(userOptions, _lang) {
// eslint-disable-next-line
docsearch(Object.assign(Object.assign({ container: "#docsearch", placeholder: this.$site.themeConfig.searchPlaceholder || "" }, userOptions), { searchParameters: userOptions.searchParameters || {},
// transform full url to route path
transformItems: (items) => items.map((item) => (Object.assign(Object.assign({}, item), {
// the `item.url` is full url with protocol and hostname
// so we have to transform it to vue-router path
url: this.resolveRoutePathFromUrl(item.url) }))),
// render the hit component with custom `onClick` handler
hitComponent: ({ hit, children }) => createElement("a", {
href: hit.url,
onClick: (event) => {
// We rely on the native link scrolling when user is
// already on the right anchor because Vue Router doesn’t
// support duplicated history entries.
if (this.$route.fullPath === hit.url)
return;
const fullPath = `${window.location.origin}${hit.url}`;
const { pathname: hitPathname } = new URL(fullPath);
// If the hits goes to another page, we prevent the native link behavior
// to leverage the Vue Router loading feature.
if (this.$route.path !== hitPathname)
event.preventDefault();
if (this.$router
.getRoutes()
.some((route) => route.path.replace(/index\.html$/, "") === hitPathname))
void this.$router.push(hit.url);
else
window.open(fullPath);
},
}, children), navigator: {
navigate: ({ itemUrl }) => {
const fullPath = `${window.location.origin}${itemUrl}`;
const { pathname: hitPathname } = new URL(fullPath);
// Vue Router doesn’t handle same-page navigation so we use
// the native browser location API for anchor navigation.
if (this.$route.path === hitPathname)
window.location.assign(fullPath);
else if (this.$router
.getRoutes()
.some((route) => route.path === hitPathname))
void this.$router.push(itemUrl);
else
window.open(fullPath);
},
navigateNewTab({ itemUrl }) {
window.open(itemUrl);
},
navigateNewWindow({ itemUrl }) {
window.open(itemUrl);
},
} }));
},
resolveRoutePathFromUrl(absoluteUrl) {
const { pathname, hash } = new URL(absoluteUrl);
return `${pathname.replace(this.$site.base, "/")}${hash}`;
},
update(options, lang) {
this.$el.innerHTML = '<div id="docsearch"></div>';
this.initialize(options, lang);
},
},
});
//# sourceMappingURL=Full.js.map
\ No newline at end of file
{"version":3,"file":"Full.js","sourceRoot":"","sources":["Full.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
import Vue from "vue";
import { SidebarHeader } from "@theme/utils/sidebar";
declare const _default: import("vue/types/vue").ExtendedVue<Vue, {}, {}, {}, {
items: SidebarHeader[];
}>;
export default _default;
import Vue from "vue";
import { isActive } from "@theme/utils/path";
const renderLink = (h, { text, link, level }) => h("RouterLink", {
props: {
to: link,
activeClass: "",
exactActiveClass: "",
},
class: {
"anchor-link": true,
[level ? `heading${level}` : ""]: level,
},
}, [h("div", {}, [text])]);
const renderChildren = (h, { children, route }) => h("ul", { class: "anchor-list" }, children.map((child) => {
const active = isActive(route, `${route.path}#${child.slug}`);
return h("li", { class: { anchor: true, active } }, [
renderLink(h, {
text: child.title,
link: `${route.path}#${child.slug}`,
level: child.level,
}),
]);
}));
export default Vue.extend({
name: "Anchor",
functional: true,
props: {
items: {
type: Array,
default: () => [],
},
},
render(h, { props, parent: { $page, $route } }) {
return h("div", { attrs: { class: "anchor-place-holder" } }, [
h("aside", { attrs: { id: "anchor" } }, [
($page.headers && $page.headers.length)
? h("div", { class: "anchor-header" }, [
"On this page"
])
: null,
h("div", { class: "anchor-wrapper" }, [
props.items.length
? renderChildren(h, {
children: props.items,
route: $route,
})
: $page.headers
? renderChildren(h, {
children: $page.headers,
route: $route,
})
: null,
]),
($page.headers && $page.headers.length)
? h("div", [
h("div", { class: "anchor-header anchor-support" }, [
"Support"
]),
h("div", { class: "anchor-support-links" }, [
h("a", { attrs: { href: "https://discord.optimism.io", target: "_blank" } }, [
h("div", [
h("i", { attrs: { class: "fab fa-discord" } }),
" Discord community"
])
]),
h("a", { attrs: { href: "https://forms.monday.com/forms/c867f3f357707ff1fb4af0d3d5080710?r=use1", target: "_blank" } }, [
h("div", [
h("i", { attrs: { class: "far fa-comment-dots" } }),
" Get support for going live"
])
]),
h("a", { attrs: { href: "https://github.com/ethereum-optimism/optimism/issues", target: "_blank" } }, [
h("div", [
h("i", { attrs: { class: "fab fa-github" } }),
" Make an issue on GitHub"
])
]),
h("a", { attrs: { href: "https://github.com/ethereum-optimism/optimism/contribute", target: "_blank" } }, [
h("div", [
h("i", { attrs: { class: "far fa-hands-helping" } }),
" Contribute to Optimism"
])
]),
])
])
: null
]),
]);
},
});
//# sourceMappingURL=Anchor.js.map
{"version":3,"file":"Anchor.js","sourceRoot":"","sources":["Anchor.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AAEtB,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAW7C,MAAM,UAAU,GAAG,CACjB,CAAgB,EAChB,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAc,EAC1B,EAAE,CACT,CAAC,CACC,YAAY,EACZ;IACE,KAAK,EAAE;QACL,EAAE,EAAE,IAAI;QACR,WAAW,EAAE,EAAE;QACf,gBAAgB,EAAE,EAAE;KACrB;IACD,KAAK,EAAE;QACL,aAAa,EAAE,IAAI;QACnB,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK;KACxC;CACF,EACD,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CACvB,CAAC;AAOJ,MAAM,cAAc,GAAG,CACrB,CAAgB,EAChB,EAAE,QAAQ,EAAE,KAAK,EAAyB,EACnC,EAAE,CACT,CAAC,CACC,IAAI,EACJ,EAAE,KAAK,EAAE,aAAa,EAAE,EACxB,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAoB,EAAE,EAAE;IACpC,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,EAAE,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAE9D,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QAClD,UAAU,CAAC,CAAC,EAAE;YACZ,IAAI,EAAE,KAAK,CAAC,KAAK;YACjB,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE;YACnC,KAAK,EAAE,KAAK,CAAC,KAAK;SACnB,CAAC;KACH,CAAC,CAAC;AACL,CAAC,CAAC,CACH,CAAC;AAEJ,eAAe,GAAG,CAAC,MAAM,CAAC;IACxB,IAAI,EAAE,QAAQ;IAEd,UAAU,EAAE,IAAI;IAEhB,KAAK,EAAE;QACL,KAAK,EAAE;YACL,IAAI,EAAE,KAAkC;YACxC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;SAClB;KACF;IAED,MAAM,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAC5C,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,qBAAqB,EAAE,EAAE,EAAE;YAC3D,CAAC,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;gBACtC,CAAC,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE;oBACpC,KAAK,CAAC,KAAK,CAAC,MAAM;wBAChB,CAAC,CAAC,cAAc,CAAC,CAAC,EAAE;4BAChB,QAAQ,EAAE,KAAK,CAAC,KAAK;4BACrB,KAAK,EAAE,MAAM;yBACd,CAAC;wBACJ,CAAC,CAAC,KAAK,CAAC,OAAO;4BACf,CAAC,CAAC,cAAc,CAAC,CAAC,EAAE;gCAChB,QAAQ,EAAE,KAAK,CAAC,OAAO;gCACvB,KAAK,EAAE,MAAM;6BACd,CAAC;4BACJ,CAAC,CAAC,IAAI;iBACT,CAAC;aACH,CAAC;SACH,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC"}
\ No newline at end of file
<script src="./Anchor" />
<style lang="stylus">
$headings = 2 3 4 5 6
.anchor-place-holder
position sticky
top: ($navbarHeight + 2rem)
max-width $contentWidth
margin 0 auto
padding 0 2.5rem
z-index 99
@media (max-width $MQNarrow)
padding 0 1.5rem
& + .theme-default-content:not(.custom)
padding-top 0
#anchor
display none
position absolute
left calc(100% + 0.5rem)
min-width 10rem
max-width 15rem
max-height 85vh
overflow-y scroll
@media (min-width $MQWide)
.has-anchor &
display block
&::-webkit-scrollbar-track-piece
background transparent
&::-webkit-scrollbar
width 3px
&::-webkit-scrollbar-thumb:vertical
background #ddd
.theme-dark &
background #333
.anchor-wrapper
position relative
padding-left 8px
&::before
content ' '
position absolute
top 0
left 0px
bottom 0
width 2px
background var(--border-color)
z-index -1
> .anchor-list
margin 0
.anchor-list
padding-left 0
.anchor
position relative
box-sizing border-box
padding 1px 8px
list-style none
line-height 1.5
&::before
content ' '
position absolute
z-index 2
top 0
bottom 0
left -8px
width 2px
background transparent
&:hover
.anchor-link
color var(--accent-color)
&.active
.anchor-link
color var(--accent-color)
&::before
background var(--accent-color)
.anchor-link
display inline-block
vertical-align middle
position relative
max-width 100%
color var(--light-grey)
> div
text-overflow ellipsis
white-space nowrap
overflow hidden
for $heading in $headings
&.heading{$heading}
padding-left ($heading * 8 - 16) px
font-size: (16 - $heading)px
</style>
import Vue from "vue";
import type { PageComputed } from "@mr-hope/vuepress-types";
declare const _default: import("vue/types/vue").ExtendedVue<Vue, unknown, unknown, {
author: string;
time: string;
tags: string[];
readingTimeContent: string;
readingTime: string;
authorText: string;
timeText: string;
tagText: string;
readingTimeText: string;
}, {
article: PageComputed;
}>;
export default _default;
import Vue from "vue";
import { capitalize } from "@mr-hope/vuepress-shared";
import AuthorIcon from "@mr-hope/vuepress-plugin-comment/lib/client/icons/AuthorIcon.vue";
import CalendarIcon from "@mr-hope/vuepress-plugin-comment/lib/client/icons/CalendarIcon.vue";
import CategoryInfo from "@mr-hope/vuepress-plugin-comment/lib/client/CategoryInfo.vue";
import TagInfo from "@mr-hope/vuepress-plugin-comment/lib/client/TagInfo.vue";
import TimerIcon from "@mr-hope/vuepress-plugin-comment/lib/client/icons/TimerIcon.vue";
export default Vue.extend({
name: "ArticleInfo",
components: {
AuthorIcon,
CalendarIcon,
CategoryInfo,
TagInfo,
TimerIcon,
},
props: {
article: { type: Object, required: true },
},
computed: {
author() {
return (this.article.frontmatter.author ||
(this.$themeConfig.author && this.article.frontmatter.author !== false
? this.$themeConfig.author
: ""));
},
time() {
const { date, time = date } = this.article.frontmatter;
if (typeof time === "string") {
if (time.indexOf("T") !== -1) {
const [dateString, temp] = time.split("T");
const [times] = temp.split(".");
return `${dateString} ${times === "00:00:00" ? "" : times}`;
}
return time;
}
return this.article.createTime || "";
},
tags() {
const { tag, tags = tag } = this.article.frontmatter;
if (typeof tags === "string")
return [capitalize(tags)];
if (Array.isArray(tags))
return tags.map((item) => capitalize(item));
return [];
},
readingTimeContent() {
return `PT${Math.max(Math.round(this.$page.readingTime.minutes), 1)}M`;
},
readingTime() {
const { minute, time } = READING_TIME_I18N[this.$localePath || "/"];
return this.article.readingTime.minutes < 1
? minute
: time.replace("$time", Math.round(this.article.readingTime.minutes).toString());
},
authorText() {
return PAGE_INFO_I18N[this.$localePath || "/"].author;
},
timeText() {
return PAGE_INFO_I18N[this.$localePath || "/"].time;
},
tagText() {
return PAGE_INFO_I18N[this.$localePath || "/"].tag;
},
readingTimeText() {
return PAGE_INFO_I18N[this.$localePath || "/"].readingTime;
},
},
});
//# sourceMappingURL=ArticleInfo.js.map
\ No newline at end of file
{"version":3,"file":"ArticleInfo.js","sourceRoot":"","sources":["ArticleInfo.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
<template>
<div v-if="author || time" class="article-info">
<!-- Author -->
<span v-if="author" :aria-label="authorText" data-balloon-pos="down">
<AuthorIcon />
<span property="author" v-text="author" />
</span>
<!-- Writing Date -->
<span
v-if="time"
class="time"
:aria-label="timeText"
data-balloon-pos="down"
>
<CalendarIcon />
<span property="datePublished" v-text="time" />
</span>
<CategoryInfo
v-if="article.frontmatter.category"
:category="article.frontmatter.category"
/>
<TagInfo v-if="tags.length !== 0" :tags="tags" />
<!-- Reading time -->
<span
v-if="readingTime"
class="read-time-info"
:aria-label="readingTimeText"
data-balloon-pos="down"
>
<TimerIcon />
<span v-text="readingTime" />
<meta property="timeRequired" :content="readingTimeContent" />
</span>
</div>
</template>
<script src="./ArticleInfo" />
<style lang="stylus">
$articleInfoTextSize ?= 14px
.article-info
color var(--dark-grey)
font-size $articleInfoTextSize
font-family Arial, Helvetica, sans-serif
& > span
display inline-block
margin-right 0.5em
line-height 1.8
@media (max-width $MQMobileNarrow)
margin-right 0.3em
font-size 0.86rem
&::after
--balloon-font-size 8px
padding 0.3em 0.6em !important
svg
position relative
bottom -0.125em
.tags-wrapper
display inline-block
.icon
width 1em
height 1em
</style>
import Vue from "vue";
import type { PageComputed } from "@mr-hope/vuepress-types";
declare const _default: import("vue/types/vue").ExtendedVue<Vue, unknown, unknown, {
isEncrypted: boolean;
excerpt: string;
}, {
article: PageComputed;
}>;
export default _default;
import Vue from "vue";
import ArticleInfo from "@theme/components/Blog/ArticleInfo.vue";
import LockIcon from "@theme/icons/LockIcon.vue";
import PresentationIcon from "@theme/icons/PresentationIcon.vue";
import StickyIcon from "@theme/icons/StickyIcon.vue";
import { getPathMatchedKeys } from "@theme/utils/encrypt";
export default Vue.extend({
name: "ArticleItem",
components: { ArticleInfo, LockIcon, StickyIcon, PresentationIcon },
props: {
article: { type: Object, required: true },
},
computed: {
isEncrypted() {
return (getPathMatchedKeys(this.$themeConfig.encrypt, this.article.path)
.length !== 0 || Boolean(this.article.frontmatter.password));
},
excerpt() {
if (this.article.excerpt)
return this.article.excerpt;
return (this.article.frontmatter.description ||
this.article.frontmatter.summary ||
"");
},
},
});
//# sourceMappingURL=ArticleItem.js.map
\ No newline at end of file
{"version":3,"file":"ArticleItem.js","sourceRoot":"","sources":["ArticleItem.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,WAAW,MAAM,wCAAwC,CAAC;AACjE,OAAO,QAAQ,MAAM,2BAA2B,CAAC;AACjD,OAAO,gBAAgB,MAAM,mCAAmC,CAAC;AACjE,OAAO,UAAU,MAAM,6BAA6B,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAK1D,eAAe,GAAG,CAAC,MAAM,CAAC;IACxB,IAAI,EAAE,aAAa;IAEnB,UAAU,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,gBAAgB,EAAE;IAEnE,KAAK,EAAE;QACL,OAAO,EAAE,EAAE,IAAI,EAAE,MAAgC,EAAE,QAAQ,EAAE,IAAI,EAAE;KACpE;IAED,QAAQ,EAAE;QACR,WAAW;YACT,OAAO,CACL,kBAAkB,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;iBAC7D,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAC9D,CAAC;QACJ,CAAC;QAED,OAAO;YACL,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO;gBAAE,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;YAEtD,OAAO,CACL,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,WAAW;gBACpC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO;gBAChC,EAAE,CACH,CAAC;QACJ,CAAC;KACF;CACF,CAAC,CAAC"}
\ No newline at end of file
<template>
<article class="article" vocab="https://schema.org/" typeof="Article">
<StickyIcon v-if="article.frontmatter.sticky" />
<header class="title" @click="$router.push(article.path)">
<LockIcon v-if="isEncrypted" />
<PresentationIcon v-if="article.frontmatter.layout === 'Slide'" />
<span property="headline">{{ article.title }}</span>
<meta
v-if="article.frontmatter.image"
property="image"
:content="$withBase(article.frontmatter.image)"
/>
</header>
<!-- eslint-disable-next-line vue/no-v-html -->
<div v-if="excerpt" class="excerpt" v-html="excerpt" />
<hr class="hr" />
<ArticleInfo :article="article" />
</article>
</template>
<script src="./ArticleItem" />
<style lang="stylus">
.article
position relative
box-sizing border-box
width 100%
margin 0 auto 20px
padding 16px 20px
background var(--bgcolor)
border-radius 6px
text-align left
box-shadow 0 1px 3px 0 var(--card-shadow-color)
@media (max-width $MQMobileNarrow)
border-radius 0
&:last-child
margin-bottom 0
&:hover
box-shadow 0 2px 6px 0 var(--card-shadow-color)
.sticky-icon
position absolute
top 0
right 0
width 40px
height 40px
fill var(--accent-color)
.sticky-text
fill var(--white)
.title
display inline-block
position relative
font-size 1.28rem
line-height 36px
&::after
content ''
position absolute
width 100%
height 2px
bottom 0
left 0
background var(--accent-color)
visibility hidden
transform scaleX(0)
transition transform 0.3s ease-in-out
&:hover
cursor pointer
&::after
visibility visible
transform scaleX(1)
.lock-icon, .presentation-icon
position relative
bottom -0.125em
display inline-block
vertical-align baseline
width 20px
height 20px
color var(--accent-color)
.excerpt
overflow hidden
line-height 1.7
h1
display none
& + p
margin-top 0.5em
p
&:first-child
margin-top 0.5em
&:last-child
margin-bottom 0.5em
// code block fix
pre
line-height 1.4
padding 1.25rem 1.5rem
margin 0.85rem 0
// line number fix
.line-numbers-mode
pre
padding-left ($lineNumbersWrapperWidth + 1) rem
// hide code demo
.code-demo-wrapper
display none
</style>
import Vue from "vue";
import type { BlogOptions } from "@theme/types";
import type { PageComputed } from "@mr-hope/vuepress-types";
declare const _default: import("vue/types/vue").ExtendedVue<Vue, {
currentPage: number;
articleList: PageComputed[];
}, {
getArticleList(): PageComputed[];
}, {
blogConfig: BlogOptions;
articlePerPage: number;
filter: ((page: PageComputed) => boolean) | undefined;
$articles: PageComputed[];
articles: PageComputed[];
}, Record<never, any>>;
export default _default;
import Vue from "vue";
import ArticleItem from "@theme/components/Blog/ArticleItem.vue";
import EmptyIcon from "@theme/icons/EmptyIcon.vue";
import MyTransition from "@theme/components/MyTransition.vue";
import { filterArticle, sortArticle } from "@theme/utils/article";
import { getPathMatchedKeys } from "@theme/utils/encrypt";
export default Vue.extend({
name: "ArticleList",
components: { ArticleItem, EmptyIcon, MyTransition },
data: () => ({
currentPage: 1,
articleList: [],
}),
computed: {
blogConfig() {
return this.$themeConfig.blog || {};
},
articlePerPage() {
return this.blogConfig.perPage || 10;
},
filter() {
const { path } = this.$route;
return path.includes("/article")
? (page) => page.frontmatter.layout !== "Slide"
: path.includes("/star")
? (page) => Boolean(page.frontmatter.star || page.frontmatter.sticky)
: path.includes("/encrypt")
? (page) => getPathMatchedKeys(this.$themeConfig.encrypt, page.path).length !==
0 || Boolean(page.frontmatter.password)
: path.includes("/slide")
? (page) => page.frontmatter.layout === "Slide"
: undefined;
},
$articles() {
// filter then sort
return sortArticle(filterArticle(this.$site.pages, this.filter), "sticky");
},
/** Articles in this page */
articles() {
return this.articleList.slice((this.currentPage - 1) * this.articlePerPage, this.currentPage * this.articlePerPage);
},
},
watch: {
// update article list when route is changed
$route(to, from) {
if (to.path !== from.path) {
this.articleList = this.getArticleList();
// reset page to 1
this.currentPage = 1;
}
},
currentPage() {
// list top border distance
const distance = document.querySelector("#article-list").getBoundingClientRect().top + window.scrollY;
setTimeout(() => {
window.scrollTo(0, distance);
}, 100);
},
},
mounted() {
this.articleList = this.getArticleList();
},
methods: {
getArticleList() {
try {
return this.$pagination
? // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
this.$pagination._matchedPages
: this.$articles;
}
catch (err) {
return this.$articles;
}
},
},
});
//# sourceMappingURL=ArticleList.js.map
\ No newline at end of file
{"version":3,"file":"ArticleList.js","sourceRoot":"","sources":["ArticleList.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
<template>
<div id="article-list" class="article-wrapper">
<EmptyIcon v-if="!articles.length" class="empty" />
<MyTransition
v-for="(article, index) in articles"
:key="article.path"
:delay="index * 0.04"
>
<ArticleItem :article="article" />
</MyTransition>
<Pagination
v-model="currentPage"
:per-page="articlePerPage"
:total="articleList.length"
/>
</div>
</template>
<script src="./ArticleList" />
<style lang="stylus">
.article-wrapper
margin-top -0.5rem - $navbarHeight
padding-top: $navbarHeight + 0.5rem
text-align center
@media (max-width $MQMobile)
margin-top -0.5rem - $navbarMobileHeight
padding-top: $navbarMobileHeight + 0.5rem
.empty
max-width 560px
margin 0 auto
text-align center
</style>
import Vue from "vue";
interface ArticleTypeItem {
text: string;
path: string;
}
declare const _default: import("vue/types/vue").ExtendedVue<Vue, unknown, {
navigate(path: string): void;
}, {
types: ArticleTypeItem[];
}, Record<never, any>>;
export default _default;
import Vue from "vue";
import { getDefaultLocale } from "@mr-hope/vuepress-shared";
import { navigate } from "@theme/utils/navigate";
export default Vue.extend({
name: "ArticleType",
computed: {
types() {
const blogI18n = this.$themeLocaleConfig.blog || getDefaultLocale().blog;
return [
{ text: blogI18n.allText, path: "/article/" },
{ text: blogI18n.star, path: "/star/" },
{ text: blogI18n.slides, path: "/slide/" },
{ text: blogI18n.encrypt, path: "/encrypt/" },
];
},
},
methods: {
navigate(path) {
navigate(path, this.$router, this.$route);
},
},
});
//# sourceMappingURL=ArticleType.js.map
\ No newline at end of file
{"version":3,"file":"ArticleType.js","sourceRoot":"","sources":["ArticleType.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAOjD,eAAe,GAAG,CAAC,MAAM,CAAC;IACxB,IAAI,EAAE,aAAa;IAEnB,QAAQ,EAAE;QACR,KAAK;YACH,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,IAAI,gBAAgB,EAAE,CAAC,IAAI,CAAC;YAEzE,OAAO;gBACL,EAAE,IAAI,EAAE,QAAQ,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE;gBAC7C,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACvC,EAAE,IAAI,EAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE;gBAC1C,EAAE,IAAI,EAAE,QAAQ,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE;aAC9C,CAAC;QACJ,CAAC;KACF;IAED,OAAO,EAAE;QACP,QAAQ,CAAC,IAAY;YACnB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5C,CAAC;KACF;CACF,CAAC,CAAC"}
\ No newline at end of file
<template>
<ul class="article-type-wrapper">
<li
v-for="type in types"
:key="type.text"
class="article-type"
:class="{ active: type.path === $route.path }"
role="navigation"
@click="navigate(type.path)"
>
<span>{{ type.text }}</span>
</li>
</ul>
</template>
<script src="./ArticleType" />
<style lang="stylus">
.article-type-wrapper
position relative
padding-left 0
font-size 18px
font-family Arial, Helvetica, sans-serif
font-weight 600
display flex
justify-content center
align-items center
list-style none
z-index 2
@media (max-width $MQMobileNarrow)
font-size 16px
.article-type
position relative
vertical-align middle
margin 0.3em 0.8em
line-height 1.2
cursor pointer
&::after
position absolute
content ' '
left 50%
right 50%
bottom -6px
height 2px
background var(--accent-color)
border-radius 1px
visibility hidden
transition left 0.2s ease-in-out, right 0.2s ease-in-out
span
transition all 0.3s ease-in-out
&.active
position relative
span
display inline-block
color var(--accent-color)
transform scale(1.1, 1.1)
&:hover, &.active
&::after
left calc(50% - 8px)
right calc(50% - 8px)
visibility visible
</style>
import Vue from "vue";
declare const _default: import("vue/types/vue").ExtendedVue<Vue, {
defaultHeroImage: string;
}, unknown, {
heroImageStyle: Record<string, string>;
bgImageStyle: Record<string, string>;
}, Record<never, any>>;
export default _default;
import Vue from "vue";
import MyTransition from "@theme/components/MyTransition.vue";
import defaultHeroImage from "@theme/assets/hero.jpg";
export default Vue.extend({
name: "BlogHero",
components: { MyTransition },
data: () => ({ defaultHeroImage }),
computed: {
heroImageStyle() {
const defaultStyle = {
maxHeight: "180px",
margin: this.$frontmatter.showTitle === false
? "6rem auto 1.5rem"
: "1rem auto",
};
return Object.assign(Object.assign({}, defaultStyle), this.$frontmatter.heroImageStyle);
},
bgImageStyle() {
const defaultBgImageStyle = {
height: "350px",
textAlign: "center",
overflow: "hidden",
};
const { bgImageStyle = {} } = this.$frontmatter;
return Object.assign(Object.assign({}, defaultBgImageStyle), bgImageStyle);
},
},
});
//# sourceMappingURL=BlogHero.js.map
\ No newline at end of file
{"version":3,"file":"BlogHero.js","sourceRoot":"","sources":["BlogHero.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,YAAY,MAAM,oCAAoC,CAAC;AAC9D,OAAO,gBAAgB,MAAM,wBAAwB,CAAC;AAEtD,eAAe,GAAG,CAAC,MAAM,CAAC;IACxB,IAAI,EAAE,UAAU;IAEhB,UAAU,EAAE,EAAE,YAAY,EAAE;IAE5B,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAElC,QAAQ,EAAE;QACR,cAAc;YACZ,MAAM,YAAY,GAAG;gBACnB,SAAS,EAAE,OAAO;gBAClB,MAAM,EACJ,IAAI,CAAC,YAAY,CAAC,SAAS,KAAK,KAAK;oBACnC,CAAC,CAAC,kBAAkB;oBACpB,CAAC,CAAC,WAAW;aAClB,CAAC;YAEF,uCACK,YAAY,GACX,IAAI,CAAC,YAAY,CAAC,cAAyC,EAC/D;QACJ,CAAC;QAED,YAAY;YACV,MAAM,mBAAmB,GAA2B;gBAClD,MAAM,EAAE,OAAO;gBACf,SAAS,EAAE,QAAQ;gBACnB,QAAQ,EAAE,QAAQ;aACnB,CAAC;YACF,MAAM,EAAE,YAAY,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC;YAEhD,uCACK,mBAAmB,GAClB,YAAuC,EAC3C;QACJ,CAAC;KACF;CACF,CAAC,CAAC"}
\ No newline at end of file
<template>
<div
v-if="$frontmatter.hero !== false"
class="blog-hero"
:class="{ full: $frontmatter.heroFullScreen }"
:style="{ ...bgImageStyle }"
>
<div
class="mask"
:style="{
background: `url(${
$frontmatter.bgImage
? $withBase($frontmatter.bgImage)
: defaultHeroImage
}) center/cover no-repeat`,
}"
/>
<MyTransition :delay="0.04">
<img
v-if="$frontmatter.heroImage"
class="hero-logo"
:style="heroImageStyle || {}"
:src="$withBase($frontmatter.heroImage)"
alt="hero"
/>
</MyTransition>
<MyTransition :delay="0.08">
<h1 v-if="$frontmatter.showTitle !== false">
{{ $frontmatter.heroText || $title || "Hope" }}
</h1>
</MyTransition>
<MyTransition :delay="0.12">
<p v-if="$description" class="description" v-text="$description" />
</MyTransition>
</div>
</template>
<script src="./BlogHero" />
<style lang="stylus">
.blog-hero
position relative
color #eee
margin-bottom 16px
height 450px
display flex
flex-direction column
justify-content center
@media (max-width $MQMobile)
height 350px
margin 0 -1.5rem 16px
@media (max-width $MQMobileNarrow)
margin 0 0 16px
&.full
height 'calc(100vh - %s)' % $navbarHeight !important
@media (max-width $MQMobile)
height 'calc(100vh - %s)' % $navbarMobileHeight !important
.mask
background-position-y top !important
.mask
position absolute
top 0
bottom 0
left 0
right 0
&:after
display block
content ' '
background var(--light-grey)
position absolute
top 0
bottom 0
left 0
right 0
z-index 1
opacity 0.2
& > :not(.mask)
position relative
z-index 2
h1
margin 0.5rem auto
font-size 36px
@media (max-width $MQNarrow)
font-size 30px
@media (max-width $MQMobile)
font-size 36px
@media (max-width $MQMobileNarrow)
font-size 30px
.hero-logo + h1
margin 0 auto
.description
margin 1.2rem auto 0
font-size 20px
@media (max-width $MQNarrow)
font-size 18px
@media (max-width $MQMobile)
font-size 20px
@media (max-width $MQMobileNarrow)
font-size 18px
</style>
import Vue from "vue";
/**
* 项目配置
*
* Project Configuration
*/
export interface ProjectOptions {
/**
* 项目类型
*
* Type of project
*/
type: "article" | "book" | "link" | "project";
/**
* 项目名称
*
* Project name
*/
name: string;
/**
* 项目描述
*
* Project desription
*/
desc?: string;
/**
* 项目封面,应为绝对路径
*
* Cover for the project, must be an absolute path
*/
cover?: string;
/**
* 项目链接
*
* Link of the project
*/
link: string;
}
declare const _default: import("vue/types/vue").ExtendedVue<Vue, unknown, unknown, unknown, Record<never, any>>;
export default _default;
import Vue from "vue";
import ArticleList from "@theme/components/Blog/ArticleList.vue";
import BlogHero from "@theme/components/Blog/BlogHero.vue";
import BlogInfo from "@BlogInfo";
import MyTransition from "@theme/components/MyTransition.vue";
import ProjectList from "@theme/components/Blog/ProjectList.vue";
export default Vue.extend({
name: "BlogHome",
components: {
ArticleList,
BlogHero,
BlogInfo,
MyTransition,
ProjectList,
},
});
//# sourceMappingURL=BlogHome.js.map
\ No newline at end of file
{"version":3,"file":"BlogHome.js","sourceRoot":"","sources":["BlogHome.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,WAAW,MAAM,wCAAwC,CAAC;AACjE,OAAO,QAAQ,MAAM,qCAAqC,CAAC;AAC3D,OAAO,QAAQ,MAAM,WAAW,CAAC;AACjC,OAAO,YAAY,MAAM,oCAAoC,CAAC;AAC9D,OAAO,WAAW,MAAM,wCAAwC,CAAC;AAwCjE,eAAe,GAAG,CAAC,MAAM,CAAC;IACxB,IAAI,EAAE,UAAU;IAEhB,UAAU,EAAE;QACV,WAAW;QACX,QAAQ;QACR,QAAQ;QACR,YAAY;QACZ,WAAW;KACZ;CACF,CAAC,CAAC"}
\ No newline at end of file
<template>
<div class="page blog">
<BlogHero />
<div class="blog-page-wrapper">
<main class="blog-home">
<MyTransition :delay="0.16">
<ProjectList />
</MyTransition>
<MyTransition :delay="0.24">
<ArticleList :key="$route.path" />
</MyTransition>
</main>
<MyTransition :delay="0.16">
<BlogInfo />
</MyTransition>
</div>
<MyTransition :delay="0.28">
<Content :key="$route.path" class="theme-default-content" custom />
</MyTransition>
</div>
</template>
<script src="./BlogHome" />
<style lang="stylus">
.page.blog
box-sizing content-box
min-height 100vh
padding-top $navbarHeight
padding-bottom 2rem
margin 0px auto
background var(--bgcolor-light)
@media (max-width $MQMobile)
padding $navbarMobileHeight 1.5rem 2rem
@media (max-width $MQMobileNarrow)
padding-left 0
padding-right 0
.blog-page-wrapper
display flex
justify-content center
align-items flex-start
margin 0 auto
@media (min-width $MQMobile)
padding 0 1rem
@media (min-width $MQNarrow)
padding 0 2rem
@media (min-width $MQWide)
padding 0
.blog-home
max-width 780px
overflow hidden
flex 1
@media (min-width $MQMobile)
margin 0 15px
.theme-default-content:empty
padding 0
</style>
import Vue from "vue";
declare const _default: import("vue/types/vue").ExtendedVue<Vue, unknown, unknown, unknown, Record<never, any>>;
export default _default;
import Vue from "vue";
import BlogInfoList from "@theme/components/Blog/BlogInfoList.vue";
import BloggerInfo from "@theme/components/Blog/BloggerInfo.vue";
import MyTransition from "@theme/components/MyTransition.vue";
export default Vue.extend({
name: "BlogInfo",
components: { BlogInfoList, BloggerInfo, MyTransition },
});
//# sourceMappingURL=BlogInfo.js.map
\ No newline at end of file
{"version":3,"file":"BlogInfo.js","sourceRoot":"","sources":["BlogInfo.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,YAAY,MAAM,yCAAyC,CAAC;AACnE,OAAO,WAAW,MAAM,wCAAwC,CAAC;AACjE,OAAO,YAAY,MAAM,oCAAoC,CAAC;AAE9D,eAAe,GAAG,CAAC,MAAM,CAAC;IACxB,IAAI,EAAE,UAAU;IAEhB,UAAU,EAAE,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE;CACxD,CAAC,CAAC"}
\ No newline at end of file
<template>
<aside class="blog-info-wrapper">
<MyTransition>
<BloggerInfo />
</MyTransition>
<MyTransition :delay="0.04">
<BlogInfoList />
</MyTransition>
</aside>
</template>
<script src="./BlogInfo" />
<style lang="stylus">
.blog-info-wrapper
.sidebar &
.blogger-info
display none
.page &
position sticky
box-sizing border-box
top ($navbarHeight + 1rem)
flex 0 0 300px
height auto
margin-bottom 12px
transition all 0.3s
@media (max-width $MQMobile)
display none
.blogger-info
margin-bottom 16px
padding 8px 0
border-radius 8px
box-shadow 0 1px 3px 0 var(--card-shadow-color)
&:hover
box-shadow 0 2px 6px 0 var(--card-shadow-color)
</style>
import ArticleIcon from "@theme/icons/ArticleIcon.vue";
declare const _default: import("vue/types/vue").ExtendedVue<{
$starArticles: import("@mr-hope/vuepress-types").PageComputed[];
} & Record<never, any> & ArticleIcon, {
active: string;
}, {
setActive(name: string): void;
navigate(path: string): void;
}, {
i18n: {
article: string;
articleList: string;
category: string;
tag: string;
timeline: string;
timelineText: string;
allText: string;
intro: string;
star: string;
slides: string;
encrypt: string;
};
articleNumber: number;
}, Record<never, any>>;
export default _default;
import { getDefaultLocale } from "@mr-hope/vuepress-shared";
import ArticleIcon from "@theme/icons/ArticleIcon.vue";
import CategoryIcon from "@mr-hope/vuepress-plugin-comment/lib/client/icons/CategoryIcon.vue";
import TagIcon from "@mr-hope/vuepress-plugin-comment/lib/client/icons/TagIcon.vue";
import TimeIcon from "@mr-hope/vuepress-plugin-comment/lib/client/icons/TimeIcon.vue";
import ArticleList from "@theme/components/Blog/ArticleList.vue";
import CategoryList from "@theme/components/Blog/CategoryList.vue";
import MyTransition from "@theme/components/MyTransition.vue";
import TagList from "@theme/components/Blog/TagList.vue";
import Timeline from "@theme/components/Blog/Timeline.vue";
import TimelineList from "@theme/components/Blog/TimelineList.vue";
import { filterArticle } from "@theme/utils/article";
import { starMixin } from "@theme/mixins/star";
export default starMixin.extend({
name: "BlogInfo",
components: {
ArticleIcon,
ArticleList,
CategoryIcon,
CategoryList,
MyTransition,
TagIcon,
TagList,
TimeIcon,
Timeline,
TimelineList,
},
data: () => ({
active: "category",
}),
computed: {
i18n() {
return this.$themeLocaleConfig.blog || getDefaultLocale().blog;
},
articleNumber() {
return filterArticle(this.$site.pages).length;
},
},
methods: {
setActive(name) {
this.active = name;
},
navigate(path) {
if (this.$route.path !== path)
void this.$router.push(path);
},
},
});
//# sourceMappingURL=BlogInfoList.js.map
\ No newline at end of file
{"version":3,"file":"BlogInfoList.js","sourceRoot":"","sources":["BlogInfoList.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,WAAW,MAAM,8BAA8B,CAAC;AACvD,OAAO,YAAY,MAAM,oEAAoE,CAAC;AAC9F,OAAO,OAAO,MAAM,+DAA+D,CAAC;AACpF,OAAO,QAAQ,MAAM,gEAAgE,CAAC;AACtF,OAAO,WAAW,MAAM,wCAAwC,CAAC;AACjE,OAAO,YAAY,MAAM,yCAAyC,CAAC;AACnE,OAAO,YAAY,MAAM,oCAAoC,CAAC;AAC9D,OAAO,OAAO,MAAM,oCAAoC,CAAC;AACzD,OAAO,QAAQ,MAAM,qCAAqC,CAAC;AAC3D,OAAO,YAAY,MAAM,yCAAyC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAI/C,eAAe,SAAS,CAAC,MAAM,CAAC;IAC9B,IAAI,EAAE,UAAU;IAEhB,UAAU,EAAE;QACV,WAAW;QACX,WAAW;QACX,YAAY;QACZ,YAAY;QACZ,YAAY;QACZ,OAAO;QACP,OAAO;QACP,QAAQ;QACR,QAAQ;QACR,YAAY;KACb;IAED,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QACX,MAAM,EAAE,UAAU;KACnB,CAAC;IAEF,QAAQ,EAAE;QACR,IAAI;YACF,OAAO,IAAI,CAAC,kBAAkB,CAAC,IAAI,IAAI,gBAAgB,EAAE,CAAC,IAAI,CAAC;QACjE,CAAC;QAED,aAAa;YACX,OAAO,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;QAChD,CAAC;KACF;IAED,OAAO,EAAE;QACP,SAAS,CAAC,IAAY;YACpB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACrB,CAAC;QAED,QAAQ,CAAC,IAAY;YACnB,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI;gBAAE,KAAK,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9D,CAAC;KACF;CACF,CAAC,CAAC"}
\ No newline at end of file
<template>
<div class="blog-info-list">
<div class="switch-wrapper">
<button class="switch-button" @click="setActive('article')">
<div
class="icon-wapper"
:class="{ active: active === 'article' }"
:aria-label="i18n.article"
data-balloon-pos="up"
>
<ArticleIcon />
</div>
</button>
<button class="switch-button" @click="setActive('category')">
<div
class="icon-wapper"
:class="{ active: active === 'category' }"
:aria-label="i18n.category"
data-balloon-pos="up"
>
<CategoryIcon />
</div>
</button>
<button class="switch-button" @click="setActive('tag')">
<div
class="icon-wapper"
:class="{ active: active === 'tag' }"
:aria-label="i18n.tag"
data-balloon-pos="up"
>
<TagIcon />
</div>
</button>
<button class="switch-button" @click="setActive('timeline')">
<div
class="icon-wapper"
:class="{ active: active === 'timeline' }"
:aria-label="i18n.timeline"
data-balloon-pos="up"
>
<TimeIcon />
</div>
</button>
</div>
<!-- Article -->
<MyTransition v-if="active === 'article'">
<div class="sticky-article-wrapper">
<div class="title" @click="navigate('/article/')">
<ArticleIcon />
<span class="num">{{ articleNumber }}</span>
{{ i18n.article }}
</div>
<hr />
<ul class="sticky-article-list">
<MyTransition
v-for="(article, index) in $starArticles"
:key="article.path"
:delay="(index + 1) * 0.08"
>
<li
class="sticky-article"
@click="navigate(article.path)"
v-text="article.title"
/>
</MyTransition>
</ul>
</div>
</MyTransition>
<!-- Category -->
<MyTransition v-if="active === 'category'">
<div class="category-wrapper">
<div
v-if="$category.list.length !== 0"
class="title"
@click="navigate('/category/')"
>
<CategoryIcon />
<span class="num">{{ $category.list.length }}</span>
{{ i18n.category }}
</div>
<hr />
<MyTransition :delay="0.04">
<CategoryList />
</MyTransition>
</div>
</MyTransition>
<!-- Tags -->
<MyTransition v-if="active === 'tag'">
<div class="tag-wrapper">
<div
v-if="$tag.list.length !== 0"
class="title"
@click="navigate('/tag/')"
>
<TagIcon />
<span class="num">{{ $tag.list.length }}</span>
{{ i18n.tag }}
</div>
<hr />
<MyTransition :delay="0.04">
<TagList />
</MyTransition>
</div>
</MyTransition>
<!-- Timeline -->
<MyTransition v-if="active === 'timeline'">
<TimelineList />
</MyTransition>
</div>
</template>
<script src="./BlogInfoList" />
<style lang="stylus">
@require '~@mr-hope/vuepress-shared/styles/reset'
.blog-info-list
margin 8px auto
padding 8px 16px
.page &
background var(--bgcolor)
border-radius 6px
box-shadow 0 1px 3px 0 var(--card-shadow-color)
&:hover
box-shadow 0 2px 6px 0 var(--card-shadow-color)
.switch-wrapper
display flex
justify-content center
margin-bottom 8px
.switch-button
button()
width 44px
height 44px
margin 0 8px
padding 4px
color var(--grey3)
&:focus
outline none
.icon-wapper
width 20px
height 20px
padding 8px
border-radius 50%
background rgba(127, 127, 127, 0.15)
.theme-dark &
background rgba(255, 255, 255, 0.15)
&:hover
cursor pointer
&.active
.theme-light &
background var(--accent-color-l10)
.theme-dark &
background var(--accent-color-d10)
.icon
width 100%
height 100%
.sticky-article-wrapper, .category-wrapper, .tag-wrapper
padding 8px 0
.title
cursor pointer
.icon
position relative
bottom -0.125rem
width 16px
height 16px
margin 0 6px
.num
position relative
margin 0 2px
font-size 22px
.sticky-article-wrapper
.sticky-article-list
margin 8px auto
.sticky-article
padding 12px 8px 4px
border-bottom 1px dashed var(--grey14)
&:hover
cursor pointer
color var(--accent-color)
.category-wrapper
.category-list-wrapper
margin 8px auto
.tag-wrapper
.tag-list-wrapper
margin 8px auto
.page &
.timeline-list-wrapper
.content
max-height 60vh
</style>
import Vue from "vue";
declare const _default: import("vue/types/vue").ExtendedVue<Vue, unknown, unknown, {
showArticles: boolean;
componentName: string;
}, Record<never, any>>;
export default _default;
import Vue from "vue";
import ArticleList from "@theme/components/Blog/ArticleList.vue";
import ArticleType from "@theme/components/Blog/ArticleType.vue";
import BlogInfo from "@BlogInfo";
import CategoryList from "@theme/components/Blog/CategoryList.vue";
import MyTransition from "@theme/components/MyTransition.vue";
import TagList from "@theme/components/Blog/TagList.vue";
import Timeline from "@theme/components/Blog/Timeline.vue";
import TimelineList from "@theme/components/Blog/TimelineList.vue";
export default Vue.extend({
name: "BlogPage",
components: {
ArticleList,
ArticleType,
BlogInfo,
CategoryList,
MyTransition,
TagList,
Timeline,
TimelineList,
},
computed: {
showArticles() {
const { path } = this.$route;
return !path.includes("/timeline");
},
componentName() {
const pathName = this.$route.path.split("/")[1];
if (["category", "tag"].includes(pathName))
return `${pathName}List`;
else if (pathName === "timeline")
return pathName;
return "articleType";
},
},
});
//# sourceMappingURL=BlogPage.js.map
\ No newline at end of file
{"version":3,"file":"BlogPage.js","sourceRoot":"","sources":["BlogPage.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,WAAW,MAAM,wCAAwC,CAAC;AACjE,OAAO,WAAW,MAAM,wCAAwC,CAAC;AACjE,OAAO,QAAQ,MAAM,WAAW,CAAC;AACjC,OAAO,YAAY,MAAM,yCAAyC,CAAC;AACnE,OAAO,YAAY,MAAM,oCAAoC,CAAC;AAC9D,OAAO,OAAO,MAAM,oCAAoC,CAAC;AACzD,OAAO,QAAQ,MAAM,qCAAqC,CAAC;AAC3D,OAAO,YAAY,MAAM,yCAAyC,CAAC;AAEnE,eAAe,GAAG,CAAC,MAAM,CAAC;IACxB,IAAI,EAAE,UAAU;IAEhB,UAAU,EAAE;QACV,WAAW;QACX,WAAW;QACX,QAAQ;QACR,YAAY;QACZ,YAAY;QACZ,OAAO;QACP,QAAQ;QACR,YAAY;KACb;IAED,QAAQ,EAAE;QACR,YAAY;YACV,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;YAE7B,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QACrC,CAAC;QAED,aAAa;YACX,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAEhD,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBAAE,OAAO,GAAG,QAAQ,MAAM,CAAC;iBAChE,IAAI,QAAQ,KAAK,UAAU;gBAAE,OAAO,QAAQ,CAAC;YAElD,OAAO,aAAa,CAAC;QACvB,CAAC;KACF;CACF,CAAC,CAAC"}
\ No newline at end of file
<template>
<main class="blog-page">
<MyTransition>
<component :is="componentName" v-if="componentName" />
</MyTransition>
<MyTransition :delay="0.24">
<ArticleList v-if="showArticles" :key="$route.path" />
</MyTransition>
</main>
</template>
<script src="./BlogPage" />
<style lang="stylus">
.blog-page
max-width 780px
flex 1
@media (min-width $MQMobile)
margin 0 15px
.article-title
font-size 1.8rem
margin 10px 15px
</style>
import MediaLinks from "@theme/components/MediaLinks.vue";
import type { BlogOptions } from "@theme/types";
declare const _default: import("vue/types/vue").ExtendedVue<{
$timelineItems: import("@mr-hope/vuepress-types").PageComputed[];
$timeline: import("@theme/mixins/timeline").TimelineItem[];
} & Record<never, any> & MediaLinks, unknown, {
navigate(url: string): void;
jumpIntro(): void;
}, {
blogConfig: BlogOptions;
bloggerName: string;
bloggerAvatar: string;
hasIntro: boolean;
hintAttr: string;
i18n: {
article: string;
articleList: string;
category: string;
tag: string;
timeline: string;
timelineText: string;
allText: string;
intro: string;
star: string;
slides: string;
encrypt: string;
};
articleNumber: number;
}, Record<never, any>>;
export default _default;
import { getDefaultLocale } from "@mr-hope/vuepress-shared";
import MediaLinks from "@theme/components/MediaLinks.vue";
import { timelineMixin } from "@theme/mixins/timeline";
import { filterArticle } from "@theme/utils/article";
import { navigate } from "@theme/utils/navigate";
export default timelineMixin.extend({
name: "BloggerInfo",
components: { MediaLinks },
computed: {
blogConfig() {
return this.$themeConfig.blog || {};
},
bloggerName() {
return (this.blogConfig.name ||
this.$themeConfig.author ||
this.$site.title ||
"");
},
bloggerAvatar() {
return this.blogConfig.avatar || this.$themeConfig.logo || "";
},
hasIntro() {
return Boolean(this.blogConfig.intro);
},
hintAttr() {
return this.hasIntro ? "aria-label" : "";
},
i18n() {
return this.$themeLocaleConfig.blog || getDefaultLocale().blog;
},
articleNumber() {
return filterArticle(this.$site.pages).length;
},
},
methods: {
navigate(url) {
navigate(url, this.$router, this.$route);
},
jumpIntro() {
if (this.hasIntro)
navigate(this.blogConfig.intro, this.$router, this.$route);
},
},
});
//# sourceMappingURL=BloggerInfo.js.map
\ No newline at end of file
{"version":3,"file":"BloggerInfo.js","sourceRoot":"","sources":["BloggerInfo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,UAAU,MAAM,kCAAkC,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAKjD,eAAe,aAAa,CAAC,MAAM,CAAC;IAClC,IAAI,EAAE,aAAa;IAEnB,UAAU,EAAE,EAAE,UAAU,EAAE;IAE1B,QAAQ,EAAE;QACR,UAAU;YACR,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,IAAI,EAAE,CAAC;QACtC,CAAC;QAED,WAAW;YACT,OAAO,CACL,IAAI,CAAC,UAAU,CAAC,IAAI;gBACpB,IAAI,CAAC,YAAY,CAAC,MAAM;gBACxB,IAAI,CAAC,KAAK,CAAC,KAAK;gBAChB,EAAE,CACH,CAAC;QACJ,CAAC;QAED,aAAa;YACX,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,IAAI,EAAE,CAAC;QAChE,CAAC;QAED,QAAQ;YACN,OAAO,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACxC,CAAC;QAED,QAAQ;YACN,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3C,CAAC;QAED,IAAI;YACF,OAAO,IAAI,CAAC,kBAAkB,CAAC,IAAI,IAAI,gBAAgB,EAAE,CAAC,IAAI,CAAC;QACjE,CAAC;QAED,aAAa;YACX,OAAO,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;QAChD,CAAC;KACF;IAED,OAAO,EAAE;QACP,QAAQ,CAAC,GAAW;YAClB,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC3C,CAAC;QAED,SAAS;YACP,IAAI,IAAI,CAAC,QAAQ;gBACf,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,KAAe,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QACzE,CAAC;KACF;CACF,CAAC,CAAC"}
\ No newline at end of file
<template>
<div class="blogger-info" vocab="https://schema.org/" typeof="Person">
<div
class="blogger"
:class="{ hasIntro }"
:[hintAttr]="hasIntro ? i18n.intro : ''"
:data-balloon-pos="hasIntro ? 'down' : ''"
role="navigation"
@click="jumpIntro"
>
<img
v-if="bloggerAvatar"
class="avatar"
:class="{ round: blogConfig.roundAvatar !== false }"
property="image"
alt="Blogger Avatar"
:src="$withBase(bloggerAvatar)"
/>
<div
v-if="bloggerName"
class="name"
property="name"
v-text="bloggerName"
/>
<meta
v-if="hasIntro"
property="url"
:content="$withBase(blogConfig.intro)"
/>
</div>
<div class="num-wrapper">
<div @click="navigate('/article/')">
<div class="num">{{ articleNumber }}</div>
<div>{{ i18n.article }}</div>
</div>
<div @click="navigate('/category/')">
<div class="num">{{ $category.list.length }}</div>
<div>{{ i18n.category }}</div>
</div>
<div @click="navigate('/tag/')">
<div class="num">{{ $tag.list.length }}</div>
<div>{{ i18n.tag }}</div>
</div>
<div @click="navigate('/timeline/')">
<div class="num">{{ $timelineItems.length }}</div>
<div>{{ i18n.timeline }}</div>
</div>
</div>
<MediaLinks />
</div>
</template>
<script src="./BloggerInfo" />
<style lang="stylus">
.blogger-info
.page &
background var(--bgcolor)
.blogger
padding 8px 0
text-align center
&.hasIntro
cursor pointer
.avatar
width 128px
height 128px
margin 0 auto
&.round
border-radius 50%
.name
margin 16px auto
font-size 22px
.num-wrapper
display flex
margin 0 auto 16px
width 80%
> div
width 25%
text-align center
font-size 13px
cursor pointer
&:hover
color var(--accent-color)
.num
position relative
margin-bottom 8px
font-weight 600
font-size 20px
</style>
import Vue from "vue";
declare const _default: import("vue/types/vue").ExtendedVue<Vue, unknown, {
capitalize: (word: string) => string;
clickCategory(path: string): void;
}, unknown, Record<never, any>>;
export default _default;
import Vue from "vue";
import { capitalize } from "@mr-hope/vuepress-shared";
import { navigate } from "@theme/utils/navigate";
export default Vue.extend({
name: "CategoryList",
methods: {
capitalize,
clickCategory(path) {
navigate(path, this.$router, this.$route);
},
},
});
//# sourceMappingURL=CategoryList.js.map
\ No newline at end of file
{"version":3,"file":"CategoryList.js","sourceRoot":"","sources":["CategoryList.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,eAAe,GAAG,CAAC,MAAM,CAAC;IACxB,IAAI,EAAE,cAAc;IAEpB,OAAO,EAAE;QACP,UAAU;QAEV,aAAa,CAAC,IAAY;YACxB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5C,CAAC;KACF;CACF,CAAC,CAAC"}
\ No newline at end of file
<template>
<ul class="category-list-wrapper">
<li
v-for="(category, index) in $category.list"
:key="category.path"
class="category"
:class="{
active: category.path === $route.path,
[`category${index % 9}`]: true,
}"
@click="clickCategory(category.path)"
>
{{ capitalize(category.name) }}
<span class="category-num">{{ category.pages.length }}</span>
</li>
</ul>
</template>
<script src="./CategoryList" />
<style lang="stylus">
$categoryListTextSize ?= 14px
.category-list-wrapper
position relative
z-index 2
padding-left 0
font-size $categoryListTextSize
font-family Arial, Helvetica, sans-serif
list-style none
.category
display inline-block
vertical-align middle
margin 0.3rem 0.6rem 0.8rem
padding 0.4rem 0.8rem
border-radius 0.25rem
box-shadow 0 1px 4px 0 var(--card-shadow-color)
color var(--dark-grey)
cursor pointer
overflow hidden
transition background-color 0.3s, color 0.3s
@media (max-width $MQMobileNarrow)
font-size 0.9rem
.category-num
display inline-block
min-width 1rem
height 1.2rem
margin-left 0.2em
padding 0 0.1rem
border-radius 0.6rem
color var(--white)
font-family sans-serif
font-size 0.7rem
line-height 1.2rem
text-align center
@require '~@mr-hope/vuepress-shared/styles/colors.styl'
for $color, $index in $colors
.category-list-wrapper .category{$index}
&, .theme-light &
background lighten($color, 90%)
&:hover
background lighten($color, 75%)
&.active
background var(--accent-color)
color var(--white)
.category-num
color var(--accent-color)
background var(--bgcolor-light)
.theme-dark &
background darken($color, 75%)
&:hover
background darken($color, 60%)
&.active
background var(--accent-color-d10)
color var(--white)
.category-num
background $color
</style>
import Vue from "vue";
declare const _default: import("vue/types/vue").ExtendedVue<Vue, unknown, {
navigate(link: string): void;
}, unknown, Record<never, any>>;
export default _default;
import Vue from "vue";
import ArticleIcon from "@theme/icons/ArticleIcon.vue";
import BookIcon from "@theme/icons/BookIcon.vue";
import LinkIcon from "@theme/icons/LinkIcon.vue";
import ProjectIcon from "@theme/icons/ProjectIcon.vue";
import { navigate } from "@theme/utils/navigate";
export default Vue.extend({
name: "ProjectList",
components: { ArticleIcon, BookIcon, LinkIcon, ProjectIcon },
methods: {
navigate(link) {
navigate(link, this.$router, this.$route);
},
},
});
//# sourceMappingURL=ProjectList.js.map
\ No newline at end of file
{"version":3,"file":"ProjectList.js","sourceRoot":"","sources":["ProjectList.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,WAAW,MAAM,8BAA8B,CAAC;AACvD,OAAO,QAAQ,MAAM,2BAA2B,CAAC;AACjD,OAAO,QAAQ,MAAM,2BAA2B,CAAC;AACjD,OAAO,WAAW,MAAM,8BAA8B,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,eAAe,GAAG,CAAC,MAAM,CAAC;IACxB,IAAI,EAAE,aAAa;IAEnB,UAAU,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE;IAE5D,OAAO,EAAE;QACP,QAAQ,CAAC,IAAY;YACnB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5C,CAAC;KACF;CACF,CAAC,CAAC"}
\ No newline at end of file
<template>
<div class="project-list">
<div
v-for="(project, index) in $frontmatter.project || []"
:key="project.name"
class="project"
:class="`project${index % 9}`"
@click="navigate(project.link)"
>
<div
v-if="project.cover"
class="cover"
:style="`background: url(${$withBase(
project.cover
)}) center/cover no-repeat;`"
/>
<component :is="`${project.type}-icon`" />
<div class="name">{{ project.name }}</div>
<div class="desc">{{ project.desc }}</div>
</div>
</div>
</template>
<script src="./ProjectList" />
<style lang="stylus">
.project-list
position relative
display flex
justify-content flex-start
align-content stretch
align-items stretch
flex-wrap wrap
font-family sans-serif
margin-bottom 12px
z-index 2
.project
position relative
width calc(50% - 40px)
background-color var(--grey14)
border-radius 8px
margin 6px 8px
padding 12px
transition background-color 0.3s, transform 0.3s
@media (min-width $MQNarrow)
width calc(33% - 40px)
@media (min-width $MQWide)
width calc(25% - 40px)
&:hover
cursor pointer
transform scale(0.98, 0.98)
.cover
content ''
opacity 0.5
top 0
left 0
bottom 0
right 0
position absolute
z-index 1
.icon
position relative
z-index 2
float right
width 20px
height 20px
.name
position relative
z-index 2
color var(--grey3)
font-size 16px
font-weight 500
.desc
position relative
z-index 2
margin 6px 0
color var(--dark-grey)
font-size 13px
@require '~@mr-hope/vuepress-shared/styles/colors.styl'
for $color, $index in $colors
.project-list .project{$index}
&, .theme-light &
background lighten($color, 90%)
&:hover
background lighten($color, 75%)
.theme-dark &
background darken($color, 75%)
&:hover
background darken($color, 60%)
</style>
import Vue from "vue";
interface TagOption {
name: string;
path: string;
}
declare const _default: import("vue/types/vue").ExtendedVue<Vue, unknown, {
isActive(name: string): boolean;
clickTag(path: string): void;
}, {
tagList: TagOption[];
}, Record<never, any>>;
export default _default;
import Vue from "vue";
import { getDefaultLocale } from "@mr-hope/vuepress-shared";
import { navigate } from "@theme/utils/navigate";
export default Vue.extend({
name: "TagList",
computed: {
tagList() {
return [
{
name:
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.$themeLocaleConfig.blog.allText ||
getDefaultLocale().blog.allText,
path: "/tag/",
},
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
...this.$tag.list,
];
},
},
methods: {
isActive(name) {
return (name ===
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
((this.$currentTag && this.$currentTag.key) ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.$themeLocaleConfig.blog.allText ||
getDefaultLocale().blog.allText));
},
clickTag(path) {
navigate(path, this.$router, this.$route);
},
},
});
//# sourceMappingURL=TagList.js.map
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment