├── .eslintignore
├── commitlint.config.js
├── static
├── icon.png
├── logo.png
├── test.png
└── hr
│ ├── 0117cbba35e51b0bce5f8c2f6a838e8a087e8ee7.png
│ ├── 02db465212d3c374a43c60fa2625cc1caeaab796.png
│ ├── 4aa545dccf7de8d4a93c2b2b8e3265ac0a26d216.png
│ ├── 4adb9255ada5b97061e610b682b8636764fe50ed.png
│ ├── 71bf2cd56882a2e97f8b3477c9256f8b09f361d3.png
│ └── db75225feabec8d8b64ee7d3c7165cd639554cbc.png
├── src
├── renderer
│ ├── css
│ │ ├── fonts
│ │ │ ├── icomoon.eot
│ │ │ ├── icomoon.ttf
│ │ │ ├── icomoon.woff
│ │ │ └── icomoon.svg
│ │ └── font.css
│ ├── store
│ │ ├── index.js
│ │ └── modules
│ │ │ ├── Running.js
│ │ │ ├── index.js
│ │ │ ├── Config.js
│ │ │ ├── Passage.js
│ │ │ └── Sync.js
│ ├── utils
│ │ ├── RendererFactory.js
│ │ ├── PosterFactory.js
│ │ ├── constants.js
│ │ ├── network.js
│ │ ├── biliNetwork.js
│ │ ├── biliapi.js
│ │ ├── renderer.js
│ │ └── languages.js
│ ├── components
│ │ ├── subcomponents
│ │ │ ├── Pending.vue
│ │ │ ├── Login.vue
│ │ │ ├── UserInfo.vue
│ │ │ └── Passage.vue
│ │ ├── Setting.vue
│ │ ├── Editor.vue
│ │ ├── Passages.vue
│ │ └── About.vue
│ ├── router
│ │ └── index.js
│ ├── main.js
│ └── App.vue
├── main
│ ├── index.dev.js
│ └── index.js
└── index.ejs
├── .codebeatignore
├── test
├── .eslintrc
├── e2e
│ ├── specs
│ │ └── Launch.spec.js
│ ├── index.js
│ └── utils.js
└── unit
│ ├── specs
│ └── Editor.spec.js
│ ├── index.js
│ └── karma.conf.js
├── .gitignore
├── Bilibili-Column-Helper.code-workspace
├── .github
└── ISSUE_TEMPLATE
│ ├── Bug_report.md
│ └── Feature_request.md
├── .eslintrc.js
├── appveyor.yml
├── .babelrc
├── .vscode
├── settings.json
└── launch.json
├── .travis.yml
├── LICENSE
├── .electron-vue
├── dev-client.js
├── webpack.main.config.js
├── build.js
├── webpack.web.config.js
├── dev-runner.js
└── webpack.renderer.config.js
├── Readme.md
├── CODE_OF_CONDUCT.md
├── CHANGELOG.md
├── package.json
└── api.txt
/.eslintignore:
--------------------------------------------------------------------------------
1 | test/unit/coverage/**
2 | test/unit/*.js
3 | test/e2e/*.js
4 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = { extends: ['@commitlint/config-conventional'] }
2 |
--------------------------------------------------------------------------------
/static/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yesterday17/Bilibili-Column-Helper/HEAD/static/icon.png
--------------------------------------------------------------------------------
/static/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yesterday17/Bilibili-Column-Helper/HEAD/static/logo.png
--------------------------------------------------------------------------------
/static/test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yesterday17/Bilibili-Column-Helper/HEAD/static/test.png
--------------------------------------------------------------------------------
/src/renderer/css/fonts/icomoon.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yesterday17/Bilibili-Column-Helper/HEAD/src/renderer/css/fonts/icomoon.eot
--------------------------------------------------------------------------------
/src/renderer/css/fonts/icomoon.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yesterday17/Bilibili-Column-Helper/HEAD/src/renderer/css/fonts/icomoon.ttf
--------------------------------------------------------------------------------
/src/renderer/css/fonts/icomoon.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yesterday17/Bilibili-Column-Helper/HEAD/src/renderer/css/fonts/icomoon.woff
--------------------------------------------------------------------------------
/.codebeatignore:
--------------------------------------------------------------------------------
1 | .github/*
2 | .vscode/*
3 | build/*
4 | dist/*
5 | .electron-vue/*
6 | test/*
7 | tests/*
8 | spec/*
9 | specs/*
10 | node_modules/*
11 |
--------------------------------------------------------------------------------
/static/hr/0117cbba35e51b0bce5f8c2f6a838e8a087e8ee7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yesterday17/Bilibili-Column-Helper/HEAD/static/hr/0117cbba35e51b0bce5f8c2f6a838e8a087e8ee7.png
--------------------------------------------------------------------------------
/static/hr/02db465212d3c374a43c60fa2625cc1caeaab796.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yesterday17/Bilibili-Column-Helper/HEAD/static/hr/02db465212d3c374a43c60fa2625cc1caeaab796.png
--------------------------------------------------------------------------------
/static/hr/4aa545dccf7de8d4a93c2b2b8e3265ac0a26d216.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yesterday17/Bilibili-Column-Helper/HEAD/static/hr/4aa545dccf7de8d4a93c2b2b8e3265ac0a26d216.png
--------------------------------------------------------------------------------
/static/hr/4adb9255ada5b97061e610b682b8636764fe50ed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yesterday17/Bilibili-Column-Helper/HEAD/static/hr/4adb9255ada5b97061e610b682b8636764fe50ed.png
--------------------------------------------------------------------------------
/static/hr/71bf2cd56882a2e97f8b3477c9256f8b09f361d3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yesterday17/Bilibili-Column-Helper/HEAD/static/hr/71bf2cd56882a2e97f8b3477c9256f8b09f361d3.png
--------------------------------------------------------------------------------
/static/hr/db75225feabec8d8b64ee7d3c7165cd639554cbc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Yesterday17/Bilibili-Column-Helper/HEAD/static/hr/db75225feabec8d8b64ee7d3c7165cd639554cbc.png
--------------------------------------------------------------------------------
/test/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "mocha": true
4 | },
5 | "globals": {
6 | "assert": true,
7 | "expect": true,
8 | "should": true,
9 | "__static": true
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | dist/electron/*
3 | dist/web/*
4 | build/*
5 | !build/icons
6 | node_modules/
7 | npm-debug.log
8 | npm-debug.log.*
9 | thumbs.db
10 | !.gitkeep
11 | yarn.lock
12 | *.log
13 | test/unit/coverage
--------------------------------------------------------------------------------
/src/renderer/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 |
4 | import modules from './modules'
5 |
6 | Vue.use(Vuex)
7 |
8 | export default new Vuex.Store({
9 | modules,
10 | strict: process.env.NODE_ENV !== 'production'
11 | })
12 |
--------------------------------------------------------------------------------
/Bilibili-Column-Helper.code-workspace:
--------------------------------------------------------------------------------
1 | {
2 | "folders": [
3 | {
4 | "path": "."
5 | }
6 | ],
7 | "settings": {
8 | "git.autofetch": true,
9 | "files.autoSave": "onFocusChange",
10 | "editor.tabCompletion": true,
11 | "eslint.alwaysShowStatus": true,
12 | "emmet.triggerExpansionOnTab": true
13 | }
14 | }
--------------------------------------------------------------------------------
/src/renderer/store/modules/Running.js:
--------------------------------------------------------------------------------
1 | const state = {
2 | page: 3,
3 | loginStatus: 'pending'
4 | }
5 |
6 | const mutations = {
7 | SET_PAGE: function (state, page) {
8 | state.page = page
9 | },
10 | UPDATE_LOGIN_STATUS: function (state, status) {
11 | state.loginStatus = status
12 | }
13 | }
14 |
15 | export default {
16 | state,
17 | mutations
18 | }
19 |
--------------------------------------------------------------------------------
/test/e2e/specs/Launch.spec.js:
--------------------------------------------------------------------------------
1 | import utils from '../utils'
2 |
3 | describe('Launch', function () {
4 | beforeEach(utils.beforeEach)
5 | afterEach(utils.afterEach)
6 |
7 | it('shows the proper application title', function () {
8 | return this.app.client.getTitle()
9 | .then(title => {
10 | expect(title).to.equal('my-project')
11 | })
12 | })
13 | })
14 |
--------------------------------------------------------------------------------
/src/renderer/utils/RendererFactory.js:
--------------------------------------------------------------------------------
1 | import biliZhuanLanMarkdown from 'bilibili-zhuanlan-markdown-tool'
2 | import * as defaultRenderer from './renderer'
3 |
4 | export function getRenderer (option) {
5 | switch (option.module) {
6 | case 'biliZhuanlanMarkdownTool':
7 | return biliZhuanLanMarkdown.md2Html
8 | case 'default':
9 | return (code) => defaultRenderer.render(code)
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/test/unit/specs/Editor.spec.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Editor from '@/components/Editor'
3 |
4 | describe('Editor.vue', () => {
5 | it('should contain both editor and previewer', () => {
6 | const vm = new Vue({
7 | el: document.createElement('div'),
8 | render: h => h(Editor)
9 | }).$mount()
10 |
11 | expect(vm.$el.querySelector('.col').textContent).to.contain('Welcome to your new project!')
12 | })
13 | })
14 |
--------------------------------------------------------------------------------
/src/renderer/store/modules/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * The file enables `@/store/index.js` to import all vuex modules
3 | * in a one-shot manner. There should not be any reason to edit this file.
4 | */
5 |
6 | const files = require.context('.', false, /\.js$/)
7 | const modules = {}
8 |
9 | files.keys().forEach(key => {
10 | if (key === './index.js') return
11 | modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default
12 | })
13 |
14 | export default modules
15 |
--------------------------------------------------------------------------------
/test/e2e/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | // Set BABEL_ENV to use proper env config
4 | process.env.BABEL_ENV = 'test'
5 |
6 | // Enable use of ES6+ on required files
7 | require('babel-register')({
8 | ignore: /node_modules/
9 | })
10 |
11 | // Attach Chai APIs to global scope
12 | const { expect, should, assert } = require('chai')
13 | global.expect = expect
14 | global.should = should
15 | global.assert = assert
16 |
17 | // Require all JS files in `./specs` for Mocha to consume
18 | require('require-dir')('./specs')
19 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/Bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: 报告Bug。
4 |
5 | ---
6 |
7 | **描述Bug**
8 | 对Bug现象的简述。
9 |
10 | **复现方式**
11 | 复现该Bug的方法。
12 | 1. 进入 '...'
13 | 2. 点击 '....'
14 | 3. 滑动到 '....'
15 | 4. 发现错误
16 |
17 | **希望达到的结果**
18 | 在这里描述你希望通过以上步骤达到的效果。
19 |
20 | **屏幕截图**
21 | 屏幕截图有助于我们理解Bug的表现形式。
22 |
23 | **错误日志**
24 | 在这里贴上`Gist`或`pastebin`的地址。(错误日志功能在建中)
25 |
26 | **操作系统(请补完下列内容):**
27 | - OS: [e.g. Windows]
28 | - Version [e.g. 1.0.0]
29 |
30 | **附加信息**
31 | 在这里增加其他的说明信息。
32 |
--------------------------------------------------------------------------------
/src/renderer/components/subcomponents/Pending.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{content}}
4 |
5 |
6 |
7 |
18 |
19 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/Feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: 提出建议。
4 |
5 | ---
6 |
7 | **请描述你的建议是否是针对某一问题提出的**
8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
9 |
10 | **描述你想要实现的解决方案**
11 | A clear and concise description of what you want to happen.
12 |
13 | **描述你已经考虑过的方案**
14 | A clear and concise description of any alternative solutions or features you've considered.
15 |
16 | **附加信息**
17 | Add any other context or screenshots about the feature request here.
18 |
--------------------------------------------------------------------------------
/test/e2e/utils.js:
--------------------------------------------------------------------------------
1 | import electron from 'electron'
2 | import { Application } from 'spectron'
3 |
4 | export default {
5 | afterEach () {
6 | this.timeout(10000)
7 |
8 | if (this.app && this.app.isRunning()) {
9 | return this.app.stop()
10 | }
11 | },
12 | beforeEach () {
13 | this.timeout(10000)
14 | this.app = new Application({
15 | path: electron,
16 | args: ['dist/electron/main.js'],
17 | startTimeout: 10000,
18 | waitTimeout: 10000
19 | })
20 |
21 | return this.app.start()
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/test/unit/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | Vue.config.devtools = false
3 | Vue.config.productionTip = false
4 |
5 | // require all test files (files that ends with .spec.js)
6 | const testsContext = require.context('./specs', true, /\.spec$/)
7 | testsContext.keys().forEach(testsContext)
8 |
9 | // require all src files except main.js for coverage.
10 | // you can also change this to match only the subset of files that
11 | // you want coverage for.
12 | const srcContext = require.context('../../src/renderer', true, /^\.\/(?!main(\.js)?$)/)
13 | srcContext.keys().forEach(srcContext)
14 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parser: "babel-eslint",
4 | parserOptions: {
5 | sourceType: "module"
6 | },
7 | env: {
8 | browser: true,
9 | node: true
10 | },
11 | extends: "standard",
12 | globals: {
13 | __static: true
14 | },
15 | plugins: ["html"],
16 | env: {
17 | es6: true
18 | },
19 | rules: {
20 | "arrow-parens": 0,
21 | "generator-star-spacing": 0,
22 | "no-debugger": process.env.NODE_ENV === "production" ? 2 : 0,
23 | "no-return-await": 0,
24 | "one-var": 0,
25 | "no-undef": 0,
26 | "no-unmodified-loop-condition": 0,
27 | "no-undef-init": 0
28 | }
29 | };
30 |
--------------------------------------------------------------------------------
/src/renderer/utils/PosterFactory.js:
--------------------------------------------------------------------------------
1 | import biliZhuanLanMarkdown from 'bilibili-zhuanlan-markdown-tool'
2 | import * as biliNetwork from './biliNetwork'
3 | import * as constants from './constants'
4 |
5 | export function getPoster (option) {
6 | switch (option.module) {
7 | case 'biliZhuanlanMarkdownTool':
8 | return (passage, cookies) => {
9 | biliZhuanLanMarkdown.initStatus(cookies)
10 | biliZhuanLanMarkdown.sendArticle(constants.localMDPath(passage.data.name))
11 | }
12 | case 'default':
13 | return (passage, cookies) => {
14 | biliNetwork.addUpdate(passage, cookies, option.renderer)
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | # Commented sections below can be used to run tests on the CI server
2 | # https://simulatedgreg.gitbooks.io/electron-vue/content/en/testing.html#on-the-subject-of-ci-testing
3 |
4 | version: 0.1.{build}
5 |
6 | branches:
7 | only:
8 | - master
9 |
10 | image: Visual Studio 2017
11 | platform:
12 | - x64
13 |
14 | cache:
15 | - node_modules
16 | - '%APPDATA%\npm-cache'
17 | - '%USERPROFILE%\.electron'
18 | - '%USERPROFILE%\AppData\Local\Yarn\cache'
19 |
20 | init:
21 | - git config --global core.autocrlf input
22 |
23 | install:
24 | - ps: Install-Product node 8 x64
25 | - git reset --hard HEAD
26 | - yarn
27 | - node --version
28 |
29 | build_script:
30 | #- yarn test
31 | #- yarn build
32 | yarn dist
33 |
34 | test: off
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "comments": false,
3 | "env": {
4 | "test": {
5 | "presets": [
6 | ["env", {
7 | "targets": { "node": 7 }
8 | }],
9 | "stage-0"
10 | ],
11 | "plugins": ["istanbul"]
12 | },
13 | "main": {
14 | "presets": [
15 | ["env", {
16 | "targets": { "node": 7 }
17 | }],
18 | "stage-0"
19 | ]
20 | },
21 | "renderer": {
22 | "presets": [
23 | ["env", {
24 | "modules": false
25 | }],
26 | "stage-0"
27 | ]
28 | },
29 | "web": {
30 | "presets": [
31 | ["env", {
32 | "modules": false
33 | }],
34 | "stage-0"
35 | ]
36 | }
37 | },
38 | "plugins": ["transform-runtime"]
39 | }
40 |
--------------------------------------------------------------------------------
/src/renderer/utils/constants.js:
--------------------------------------------------------------------------------
1 | import { remote } from 'electron'
2 | import * as path from 'path'
3 |
4 | export const PATH = path.resolve(remote.app.getPath('userData'), 'Passages')
5 |
6 | export let columnPath = (name) => path.resolve(PATH, name)
7 | export let imagePath = (name) => path.resolve(columnPath(name), 'images')
8 | export let documentPath = (name) => path.resolve(columnPath(name), 'document')
9 | export let indexJson = (name) => path.resolve(columnPath(name), 'index.json')
10 |
11 | export let localMDPath = (name) => path.resolve(documentPath(name), 'local.md')
12 | export let remoteMDPath = (name) => path.resolve(documentPath(name), 'remote.md')
13 | export let localCoverPath = (name) => path.resolve(imagePath(name), 'cover.png')
14 |
15 | export let resolveImagePath = (name, path)
16 |
--------------------------------------------------------------------------------
/src/renderer/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 |
4 | Vue.use(Router)
5 |
6 | export default new Router({
7 | routes: [
8 | {
9 | path: '/passages',
10 | name: 'passages',
11 | component: require('@/components/Passages').default
12 | },
13 | {
14 | path: '/editor',
15 | name: 'editor',
16 | component: require('@/components/Editor').default
17 | },
18 | {
19 | path: '/setting',
20 | name: 'setting',
21 | component: require('@/components/Setting').default
22 | },
23 | {
24 | path: '/about',
25 | name: 'about',
26 | component: require('@/components/About').default
27 | },
28 | {
29 | path: '*',
30 | redirect: '/setting'
31 | }
32 | ]
33 | })
34 |
--------------------------------------------------------------------------------
/src/main/index.dev.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is used specifically and only for development. It installs
3 | * `electron-debug` & `vue-devtools`. There shouldn't be any need to
4 | * modify this file, but it can be used to extend your development
5 | * environment.
6 | */
7 |
8 | /* eslint-disable */
9 |
10 | // Install `electron-debug` with `devtron`
11 | require('electron-debug')({ showDevTools: true })
12 |
13 | // Install `vue-devtools`
14 | require('electron').app.on('ready', () => {
15 | let installExtension = require('electron-devtools-installer')
16 | installExtension.default(installExtension.VUEJS_DEVTOOLS)
17 | .then(() => {})
18 | .catch(err => {
19 | console.log('Unable to install `vue-devtools`: \n', err)
20 | })
21 | })
22 |
23 | // Require `main` process to boot app
24 | require('./index')
25 |
--------------------------------------------------------------------------------
/src/renderer/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import ElementUI from 'element-ui'
3 | import axios from 'axios'
4 | import VueCodemirror from 'vue-codemirror'
5 | import directive from 'element-ui/packages/popover/src/directive'
6 |
7 | import App from './App'
8 | import router from './router'
9 | import store from './store'
10 |
11 | /* Import css files here */
12 | import 'element-ui/lib/theme-chalk/index.css'
13 | import './css/font.css'
14 |
15 | if (!process.env.IS_WEB) Vue.use(require('vue-electron'))
16 | Vue.http = Vue.prototype.$http = axios
17 | Vue.config.productionTip = false
18 | Vue.use(VueCodemirror)
19 | Vue.use(ElementUI)
20 | Vue.directive('popover', directive)
21 |
22 | /* eslint-disable no-new */
23 | new Vue({
24 | components: { App },
25 | router,
26 | store,
27 | template: ' '
28 | }).$mount('#app')
29 |
--------------------------------------------------------------------------------
/src/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | bilibili-column-helper
7 | <% if (htmlWebpackPlugin.options.nodeModules) { %>
8 |
9 |
12 | <% } %>
13 |
14 |
15 |
16 |
17 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "git.autofetch": true,
3 | "files.autoSave": "onFocusChange",
4 | "editor.tabSize": 2,
5 | "editor.tabCompletion": true,
6 | "eslint.alwaysShowStatus": true,
7 | "eslint.validate": [
8 | "javascript",
9 | "javascriptreact",
10 | "vue",
11 | {
12 | "language": "html",
13 | "autoFix": true
14 | }
15 | ],
16 | "prettier.eslintIntegration": true,
17 | "vetur.format.defaultFormatter.js": "none",
18 | "todohighlight.include": [
19 | "**/*.js",
20 | "**/*.jsx",
21 | "**/*.ts",
22 | "**/*.tsx",
23 | "**/*.html",
24 | "**/*.php",
25 | "**/*.css",
26 | "**/*.scss",
27 | "**/*.vue"
28 | ],
29 | "todohighlight.isEnable": true,
30 | "vetur.format.defaultFormatter.html": "js-beautify-html",
31 | "emmet.triggerExpansionOnTab": true,
32 | "files.exclude": {
33 | "node_modules/": true,
34 | ".electron-vue": true
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "name": "Launch",
6 | "type": "node",
7 | "request": "launch",
8 | "program": "${workspaceRoot}/.electron-vue/dev-runner.js",
9 | "stopOnEntry": false,
10 | "args": [],
11 | "cwd": "${workspaceRoot}",
12 | // this points to the electron task runner
13 | "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
14 | "runtimeArgs": ["--nolazy"],
15 | "env": {
16 | "NODE_ENV": "production"
17 | },
18 | "externalConsole": false,
19 | "sourceMaps": false,
20 | "outDir": null
21 | },
22 | {
23 | "name": "Attach",
24 | "type": "node",
25 | "request": "attach",
26 | "port": 5858,
27 | "sourceMaps": false,
28 | "outDir": null,
29 | "localRoot": "${workspaceRoot}",
30 | "remoteRoot": null
31 | }
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | osx_image: xcode8.3
2 | sudo: required
3 | dist: trusty
4 | language: c
5 | matrix:
6 | include:
7 | - os: osx
8 | - os: linux
9 | env: CC=clang CXX=clang++ npm_config_clang=1
10 | compiler: clang
11 | cache:
12 | directories:
13 | - node_modules
14 | - "$HOME/.electron"
15 | - "$HOME/.cache"
16 | addons:
17 | apt:
18 | packages:
19 | - libgnome-keyring-dev
20 | - icnsutils
21 | before_install:
22 | - mkdir -p /tmp/git-lfs && curl -L https://github.com/github/git-lfs/releases/download/v1.2.1/git-lfs-$([
23 | "$TRAVIS_OS_NAME" == "linux" ] && echo "linux" || echo "darwin")-amd64-1.2.1.tar.gz
24 | | tar -xz -C /tmp/git-lfs --strip-components 1 && /tmp/git-lfs/git-lfs pull
25 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install --no-install-recommends -y icnsutils graphicsmagick xz-utils; fi
26 | install:
27 | - nvm install 8
28 | - curl -o- -L https://yarnpkg.com/install.sh | bash
29 | - source ~/.bashrc
30 | - npm install -g xvfb-maybe
31 | - yarn
32 | script:
33 | - yarn run dist
34 | branches:
35 | only:
36 | - master
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Yesterday17
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/renderer/utils/network.js:
--------------------------------------------------------------------------------
1 | const request = require('request-promise').defaults({
2 | jar: true
3 | })
4 |
5 | export async function get (options) {
6 | return await request(options)
7 | }
8 |
9 | export async function post (options) {
10 | return await request(options)
11 | }
12 |
13 | export async function getBilibili (uri, cookies) {
14 | const options = getConfig(uri, 'GET', cookies)
15 | return JSON.parse(await get(options))
16 | }
17 |
18 | export async function postBilibili (uri, cookies, form) {
19 | const options = getConfig(uri, 'POST', cookies)
20 | options['form'] = form
21 | return JSON.parse(await post(options))
22 | }
23 |
24 | function getConfig (uri, method, cookies) {
25 | return {
26 | uri: uri,
27 | method: method,
28 | gzip: true,
29 | headers: {
30 | 'Connection': 'keep-alive',
31 | 'Cache-Control': 'max-age=0',
32 | 'Upgrade-Insecure-Requests': 1,
33 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.84 Safari/537.36',
34 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
35 | 'Accept-Encoding': 'gzip, deflate, br',
36 | 'Accept-Language': 'zh-CN,zh;q=0.9',
37 | 'Cookie': cookies
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/.electron-vue/dev-client.js:
--------------------------------------------------------------------------------
1 | const hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
2 |
3 | hotClient.subscribe(event => {
4 | /**
5 | * Reload browser when HTMLWebpackPlugin emits a new index.html
6 | *
7 | * Currently disabled until jantimon/html-webpack-plugin#680 is resolved.
8 | * https://github.com/SimulatedGREG/electron-vue/issues/437
9 | * https://github.com/jantimon/html-webpack-plugin/issues/680
10 | */
11 | // if (event.action === 'reload') {
12 | // window.location.reload()
13 | // }
14 |
15 | /**
16 | * Notify `mainWindow` when `main` process is compiling,
17 | * giving notice for an expected reload of the `electron` process
18 | */
19 | if (event.action === 'compiling') {
20 | document.body.innerHTML += `
21 |
34 |
35 |
36 | Compiling Main Process...
37 |
38 | `
39 | }
40 | })
41 |
--------------------------------------------------------------------------------
/src/renderer/store/modules/Config.js:
--------------------------------------------------------------------------------
1 | import Store from 'electron-store'
2 |
3 | let s = new Store({
4 | name: 'config'
5 | })
6 | const state = {
7 | config: {
8 | version: '',
9 |
10 | renderer: '',
11 | poster: '',
12 |
13 | cookies: [],
14 | cookie: '',
15 |
16 | favoriteTags: []
17 | }
18 | }
19 |
20 | const mutations = {
21 | LOAD_CONFIG (state) {
22 | // state.xxx = s.get('')
23 | state.config.version = s.get('version', '1.0.0')
24 | state.config.renderer = s.get('renderer', 'default')
25 | state.config.poster = s.get('poster', 'default')
26 |
27 | state.config.cookies = s.get('cookies', [])
28 | state.config.cookie = s.get('cookie', '')
29 |
30 | state.config.favoriteTags = s.get('favoriteTags', [1, 2, 3])
31 | },
32 | SAVE_CONFIG (state) {
33 | s.set(state.config)
34 | },
35 | UPDATE_COOKIES (state, cookies) {
36 | state.config.cookies = JSON.parse(JSON.stringify(cookies))
37 | state.config.cookie = cookies
38 | .map(cookie => `${cookie.name}=${cookie.value}`)
39 | .join(';')
40 | },
41 | UPDATE_COOKIE (state, cookie) {
42 | // Clear cookies
43 | state.config.cookies.splice(1, state.config.cookies.splice.length)
44 | state.config.cookie = cookie
45 | for (let item of cookie.match(/([^=; ]+=[^=; ]+)/g)) {
46 | let ans = /([^=]+)=([^=]+)/.exec(item)
47 | state.config.cookies.push({
48 | name: ans[1],
49 | value: ans[2]
50 | })
51 | }
52 | },
53 | RESET_COOKIES (state) {
54 | state.config.cookies.splice(0, state.config.cookies.length)
55 | state.config.cookie = ''
56 | }
57 | }
58 |
59 | export default {
60 | state,
61 | mutations
62 | }
63 |
--------------------------------------------------------------------------------
/test/unit/karma.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const path = require('path')
4 | const merge = require('webpack-merge')
5 | const webpack = require('webpack')
6 |
7 | const baseConfig = require('../../.electron-vue/webpack.renderer.config')
8 | const projectRoot = path.resolve(__dirname, '../../src/renderer')
9 |
10 | // Set BABEL_ENV to use proper preset config
11 | process.env.BABEL_ENV = 'test'
12 |
13 | let webpackConfig = merge(baseConfig, {
14 | devtool: '#inline-source-map',
15 | plugins: [
16 | new webpack.DefinePlugin({
17 | 'process.env.NODE_ENV': '"testing"'
18 | })
19 | ]
20 | })
21 |
22 | // don't treat dependencies as externals
23 | delete webpackConfig.entry
24 | delete webpackConfig.externals
25 | delete webpackConfig.output.libraryTarget
26 |
27 | // apply vue option to apply isparta-loader on js
28 | webpackConfig.module.rules
29 | .find(rule => rule.use.loader === 'vue-loader').use.options.loaders.js = 'babel-loader'
30 |
31 | module.exports = config => {
32 | config.set({
33 | browsers: ['visibleElectron'],
34 | client: {
35 | useIframe: false
36 | },
37 | coverageReporter: {
38 | dir: './coverage',
39 | reporters: [
40 | { type: 'lcov', subdir: '.' },
41 | { type: 'text-summary' }
42 | ]
43 | },
44 | customLaunchers: {
45 | 'visibleElectron': {
46 | base: 'Electron',
47 | flags: ['--show']
48 | }
49 | },
50 | frameworks: ['mocha', 'chai'],
51 | files: ['./index.js'],
52 | preprocessors: {
53 | './index.js': ['webpack', 'sourcemap']
54 | },
55 | reporters: ['spec', 'coverage'],
56 | singleRun: true,
57 | webpack: webpackConfig,
58 | webpackMiddleware: {
59 | noInfo: true
60 | }
61 | })
62 | }
63 |
--------------------------------------------------------------------------------
/src/renderer/utils/biliNetwork.js:
--------------------------------------------------------------------------------
1 | import * as fs from 'fs'
2 | import * as network from './network'
3 |
4 | export async function getUserInfo (cookies) {
5 | const result = await network.getBilibili(
6 | 'https://member.bilibili.com/x/web/data/article',
7 | cookies
8 | )
9 | if (result['code'] === 0) {
10 | return result['data']
11 | } else {
12 | return undefined
13 | }
14 | }
15 |
16 | export async function upcover (image, cookies) {
17 | if (typeof cookies !== 'string') return
18 |
19 | const result = await network.postBilibili('https://member.bilibili.com/x/web/article/upcover', cookies, {
20 | cover: image,
21 | csrf: cookies.match(/bili_jct=([^;]+)/)[1]
22 | })
23 | return result
24 | }
25 |
26 | export async function upcoverLocal (imagePath, cookies) {
27 | return await upcover('data:image/png;base64,' + fs.readFileSync(imagePath).toString('base64'), cookies)
28 | }
29 |
30 | export async function addUpdate (passage, cookies, renderer) {
31 | if (typeof cookies !== 'string') return
32 |
33 | const cover = await upcoverLocal(passage.data.image, cookies)
34 | console.log(cover)
35 |
36 | const result = await network.postBilibili('http://api.bilibili.com/x/article/creative/draft/addupdate', cookies, {
37 | title: passage.data.name,
38 | banner_url: cover['data']['url'],
39 | content: renderer(passage.content.local), // TODO: Use Remote instead.
40 | summary: '',
41 | words: passage.content.local.length, // TODO: Use Remote instead.
42 | category: passage.data.subtype,
43 | list_id: 0,
44 | tid: 4,
45 | reprint: 0,
46 | tags: passage.data.tags,
47 | image_urls: '',
48 | origin_image_urls: '',
49 | dynamic_intro: '',
50 | csrf: cookies.match(/bili_jct=([^;]+)/)[1]
51 | })
52 | console.log(result)
53 | return result
54 | }
55 |
--------------------------------------------------------------------------------
/src/renderer/css/font.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'icomoon';
3 | src: url('fonts/icomoon.eot?agyqrb');
4 | src: url('fonts/icomoon.eot?agyqrb#iefix') format('embedded-opentype'),
5 | url('fonts/icomoon.ttf?agyqrb') format('truetype'),
6 | url('fonts/icomoon.woff?agyqrb') format('woff'),
7 | url('fonts/icomoon.svg?agyqrb#icomoon') format('svg');
8 | font-weight: normal;
9 | font-style: normal;
10 | }
11 |
12 | [class^="icon-"], [class*=" icon-"] {
13 | /* use !important to prevent issues with browser extensions that change fonts */
14 | font-family: 'icomoon' !important;
15 | speak: none;
16 | font-style: normal;
17 | font-weight: normal;
18 | font-variant: normal;
19 | text-transform: none;
20 | line-height: 1;
21 |
22 | /* Better Font Rendering =========== */
23 | -webkit-font-smoothing: antialiased;
24 | -moz-osx-font-smoothing: grayscale;
25 | }
26 |
27 | .icon-coin-yen:before {
28 | content: "\e93e";
29 | }
30 | .icon-enlarge:before {
31 | content: "\e989";
32 | }
33 | .icon-enlarge2:before {
34 | content: "\e98b";
35 | }
36 | .icon-eye:before {
37 | content: "\e9ce";
38 | }
39 | .icon-eye-plus:before {
40 | content: "\e9cf";
41 | }
42 | .icon-eye-minus:before {
43 | content: "\e9d0";
44 | }
45 | .icon-eye-blocked:before {
46 | content: "\e9d1";
47 | }
48 | .icon-star-empty:before {
49 | content: "\e9d7";
50 | }
51 | .icon-star-half:before {
52 | content: "\e9d8";
53 | }
54 | .icon-star-full:before {
55 | content: "\e9d9";
56 | }
57 | .icon-heart:before {
58 | content: "\e9da";
59 | }
60 | .icon-minus:before {
61 | content: "\ea0b";
62 | }
63 | .icon-cancel-circle:before {
64 | content: "\ea0d";
65 | }
66 | .icon-cross:before {
67 | content: "\ea0f";
68 | }
69 | .icon-exit:before {
70 | content: "\ea14";
71 | }
72 | .icon-chat:before {
73 | content: "\e901";
74 | }
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | # Bilibili Column Helper - Bilibili 专栏助手
2 |
3 | [](https://travis-ci.org/Yesterday17/Bilibili-Column-Helper)
4 | [](https://ci.appveyor.com/project/Yesterday17/bilibili-column-helper)
5 | [](https://codebeat.co/projects/github-com-yesterday17-bilibili-column-helper-master-6e10e5a7-4172-448c-9dee-b3ddf67b0aa4)
6 |
7 | ## 原理
8 |
9 | 本程序以 Electron、Vue.js、Marked 以及 CodeMirror 为主要组件编写,旨在以 Markdown 书写目前并不支持 Markdown 的 Bilibili 专栏。
10 | 从原理来看,本程序将要实现的是将 Bilibili 支持的 HTML 特性以原本的方式渲染;而对于不支持的特性(比如表格等),则进行图片的渲染,以达到相同的显示目的。
11 |
12 | ### 用户隐私
13 |
14 | 本程序通过 Bilibili 提供的 Ajax 登录界面,实现 Bilibili 账户的登录。账户的使用仅限图片的上传以及专栏内容的上传。
15 |
16 | ## 合作开发(Contribution)
17 |
18 | 本工程基于`electron-vue`开发,其有相对完善的[中文文档](https://simulatedgreg.gitbooks.io/electron-vue/content/cn/)可供参考。
19 | 前端框架使用的是`Vue.js`,文档[点此访问](https://cn.vuejs.org/)。
20 | UI 使用的是`Element`,文档[点此访问](http://element-cn.eleme.io)。
21 | 以及`Electron`的文档:[点此访问](https://electronjs.org/)。
22 |
23 | ### 构建过程
24 |
25 | 构建基于 yarn,如果没有安装 yarn 的话就需要执行第一步。在部分系统下(如 Ubuntu 等)使用`npm install -g`时需要带上`sudo`。
26 |
27 | ```
28 | npm install -g yarn
29 | yarn install
30 | ```
31 |
32 | 如果在上述过程中遇到 electron 无法下载,可以选择使用`cnpm`或`npm`过渡:
33 |
34 | ```
35 | cnpm install
36 | ```
37 |
38 | 然后就可以通过以下步骤运行:
39 |
40 | ```
41 | yarn dev
42 | ```
43 |
44 | 如果需要打包,则需要运行:
45 |
46 | ```
47 | yarn run build
48 | ```
49 |
50 | # Credits
51 |
52 | [Bilibili zhuanlan Markdown-Tool](https://github.com/zihengCat/bilibili-zhuanlan-markdown-tool)
53 |
54 | Icons made by [Freepik](http://www.freepik.com) from [www.flaticon.com](https://www.flaticon.com/) is licensed by [Creative Commons BY 3.0](http://creativecommons.org/licenses/by/3.0/).
--------------------------------------------------------------------------------
/src/renderer/components/subcomponents/Login.vue:
--------------------------------------------------------------------------------
1 |
2 | 您现在还没有登录!请
3 | 登录 !
4 |
5 |
6 |
59 |
60 |
70 |
--------------------------------------------------------------------------------
/.electron-vue/webpack.main.config.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | process.env.BABEL_ENV = 'main'
4 |
5 | const path = require('path')
6 | const { dependencies } = require('../package.json')
7 | const webpack = require('webpack')
8 |
9 | const BabiliWebpackPlugin = require('babili-webpack-plugin')
10 |
11 | let mainConfig = {
12 | entry: {
13 | main: path.join(__dirname, '../src/main/index.js')
14 | },
15 | externals: [...Object.keys(dependencies || {})],
16 | module: {
17 | rules: [
18 | {
19 | test: /\.(js)$/,
20 | enforce: 'pre',
21 | exclude: /node_modules/,
22 | use: {
23 | loader: 'eslint-loader',
24 | options: {
25 | formatter: require('eslint-friendly-formatter')
26 | }
27 | }
28 | },
29 | {
30 | test: /\.js$/,
31 | use: 'babel-loader',
32 | exclude: /node_modules/
33 | },
34 | {
35 | test: /\.node$/,
36 | use: 'node-loader'
37 | }
38 | ]
39 | },
40 | node: {
41 | __dirname: process.env.NODE_ENV !== 'production',
42 | __filename: process.env.NODE_ENV !== 'production'
43 | },
44 | output: {
45 | filename: '[name].js',
46 | libraryTarget: 'commonjs2',
47 | path: path.join(__dirname, '../dist/electron')
48 | },
49 | plugins: [],
50 | resolve: {
51 | extensions: ['.js', '.json', '.node']
52 | },
53 | target: 'electron-main'
54 | }
55 |
56 | /**
57 | * Adjust mainConfig for development settings
58 | */
59 | if (process.env.NODE_ENV !== 'production') {
60 | mainConfig.plugins.push(
61 | new webpack.DefinePlugin({
62 | '__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"`
63 | })
64 | )
65 | }
66 |
67 | /**
68 | * Adjust mainConfig for production settings
69 | */
70 | if (process.env.NODE_ENV === 'production') {
71 | mainConfig.plugins.push(
72 | new BabiliWebpackPlugin()
73 | )
74 | }
75 |
76 | module.exports = mainConfig
77 |
--------------------------------------------------------------------------------
/src/main/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import { app, BrowserWindow, globalShortcut } from 'electron'
4 |
5 | /**
6 | * Set `__static` path to static files in production
7 | * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html
8 | */
9 | if (process.env.NODE_ENV !== 'development') {
10 | global.__statihtmlWebc = require('path')
11 | .join(__dirname, '/static')
12 | .replace(/\\/g, '\\\\')
13 | }
14 |
15 | let mainWindow
16 | const winURL =
17 | process.env.NODE_ENV === 'development'
18 | ? `http://localhost:9080`
19 | : `file://${__dirname}/index.html`
20 |
21 | function createWindow () {
22 | mainWindow = new BrowserWindow({
23 | height: 720,
24 | minHeight: 720,
25 | useContentSize: true,
26 | width: 1280,
27 | minWidth: 1280,
28 | frame: false,
29 | webPreferences: {
30 | webSecurity: false
31 | }
32 | })
33 |
34 | mainWindow.loadURL(winURL)
35 |
36 | globalShortcut.register('F8', function () {
37 | let win = BrowserWindow.getFocusedWindow()
38 | if (!win) return
39 | win.webContents.toggleDevTools()
40 | })
41 |
42 | mainWindow.on('closed', () => {
43 | mainWindow = null
44 | })
45 | }
46 |
47 | app.on('ready', createWindow)
48 |
49 | app.on('window-all-closed', () => {
50 | if (process.platform !== 'darwin') {
51 | app.quit()
52 | }
53 | })
54 |
55 | app.on('activate', () => {
56 | if (mainWindow === null) {
57 | createWindow()
58 | }
59 | })
60 |
61 | /**
62 | * Auto Updater
63 | *
64 | * Uncomment the following code below and install `electron-updater` to
65 | * support auto updating. Code Signing with a valid certificate is required.
66 | * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-electron-builder.html#auto-updating
67 | */
68 |
69 | /*
70 | import { autoUpdater } from 'electron-updater'
71 |
72 | autoUpdater.on('update-downloaded', () => {
73 | autoUpdater.quitAndInstall()
74 | })
75 |
76 | app.on('ready', () => {
77 | if (process.env.NODE_ENV === 'production') autoUpdater.checkForUpdates()
78 | })
79 | */
80 |
--------------------------------------------------------------------------------
/src/renderer/utils/biliapi.js:
--------------------------------------------------------------------------------
1 | const request = require('../../../../../../AppData/Local/Microsoft/TypeScript/2.9/node_modules/@types/request').defaults({
2 | jar: true
3 | })
4 | const fs = require('fs')
5 |
6 | function upcover (file, cookies, csrf, callback) {
7 | request.post(
8 | 'https://member.bilibili.com/x/web/article/upcover',
9 | {
10 | form: {
11 | cover: createBase64Image(fs.readFileSync(file)),
12 | csrf: csrf
13 | },
14 | headers: {
15 | Origin: 'https://member.bilibili.com',
16 | Host: 'member.bilibili.com',
17 | Connection: 'keep-alive',
18 | 'X-Requested-With': 'XMLHttpRequest',
19 | 'User-Agent':
20 | 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36',
21 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
22 | Referer: 'https://member.bilibili.com/article-text/home?',
23 | Accept: '*/*',
24 | 'Accept-Encoding': 'gzip, deflate, br',
25 | 'Accept-Language': 'zh-CN,zh;q=0.9',
26 | Cookie: cookies
27 | },
28 | timeout: 3e4
29 | },
30 | (err, response, body) => {
31 | if (!err) callback(response.body)
32 | }
33 | )
34 | }
35 |
36 | function addUpdate (cookies, csrf, callback) {
37 | request.post(
38 | 'http://api.bilibili.com/x/article/creative/draft/addupdate',
39 | {
40 | form: {
41 | title: '==',
42 | banner_url: '',
43 | content: '',
44 | summary: '',
45 | words: 0,
46 | category: 0,
47 | list_id: 0,
48 | tid: 4,
49 | reprint: 0,
50 | tags: [],
51 | image_urls: '',
52 | origin_image_urls: '',
53 | dynamic_intro: '',
54 | csrf: csrf
55 | },
56 | headers: {
57 | Accept: 'application/json, text/javascript, */*; q=0.01',
58 | 'Accept-Encoding': 'gzip, deflate',
59 | 'Accept-Language': 'zh-CN,zh;q=0.9',
60 | Connection: 'keep-alive',
61 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
62 | Cookie: cookies,
63 | Host: 'api.bilibili.com',
64 | Origin: 'http://member.bilibili.com',
65 | Referer: 'http://member.bilibili.com/article-text/home?',
66 | 'User-Agent':
67 | 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36'
68 | }
69 | },
70 | (err, response, body) => {
71 | if (!err) callback(response.body)
72 | }
73 | )
74 | }
75 |
76 | function createBase64Image (stream) {
77 | return 'data:image/bmp;base64,' + stream.toString('base64')
78 | }
79 |
80 | exports.upcover = upcover
81 | exports.addUpdate = addUpdate
82 |
--------------------------------------------------------------------------------
/src/renderer/components/subcomponents/UserInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 阅读量
5 | {{$store.state.Sync.count.view}}
6 |
10 |
11 |
12 |
13 | 评论
14 | {{$store.state.Sync.count.reply}}
15 |
19 |
20 |
21 |
22 | 喜欢
23 | {{$store.state.Sync.count.like}}
24 |
28 |
29 |
30 |
31 | 收藏
32 | {{$store.state.Sync.count.fav}}
33 |
37 |
38 |
39 |
40 | 投币
41 | {{$store.state.Sync.count.coin}}
42 |
46 |
47 |
48 |
49 |
50 |
51 |
62 |
63 |
101 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | ## Our Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment include:
10 |
11 | * Using welcoming and inclusive language
12 | * Being respectful of differing viewpoints and experiences
13 | * Gracefully accepting constructive criticism
14 | * Focusing on what is best for the community
15 | * Showing empathy towards other community members
16 |
17 | Examples of unacceptable behavior by participants include:
18 |
19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | * Trolling, insulting/derogatory comments, and personal or political attacks
21 | * Public or private harassment
22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | * Other conduct which could reasonably be considered inappropriate in a professional setting
24 |
25 | ## Our Responsibilities
26 |
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 |
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | ## Scope
32 |
33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 |
35 | ## Enforcement
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at t@yesterday17.cn. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 |
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 |
41 | ## Attribution
42 |
43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44 |
45 | [homepage]: http://contributor-covenant.org
46 | [version]: http://contributor-covenant.org/version/1/4/
47 |
--------------------------------------------------------------------------------
/src/renderer/utils/renderer.js:
--------------------------------------------------------------------------------
1 | import marked from 'marked'
2 | import Prism from 'prismjs'
3 | import * as languages from './languages'
4 |
5 | // https://github.com/jGleitz/markdown-it-prism/blob/master/index.js
6 |
7 | function RendererException (message) {
8 | this.message = message
9 | }
10 |
11 | const cutoff = [
12 | '//i0.hdslb.com/bfs/article/',
13 | '0117cbba35e51b0bce5f8c2f6a838e8a087e8ee7.png',
14 | '4aa545dccf7de8d4a93c2b2b8e3265ac0a26d216.png',
15 | '71bf2cd56882a2e97f8b3477c9256f8b09f361d3.png',
16 | 'db75225feabec8d8b64ee7d3c7165cd639554cbc.png',
17 | '4adb9255ada5b97061e610b682b8636764fe50ed.png',
18 | '02db465212d3c374a43c60fa2625cc1caeaab796.png'
19 | ]
20 |
21 | function loadPrismLang (lang, oriLang) {
22 | let langObject = Prism.languages[lang]
23 | try {
24 | if (langObject === undefined) {
25 | if (
26 | languages.unSupported.indexOf(lang) !== -1 ||
27 | (!languages.languagesC.has(lang.toUpperCase()) &&
28 | !languages.languagesC.has(oriLang.toUpperCase()))
29 | ) {
30 | throw new RendererException(lang)
31 | }
32 | require('prismjs/components/prism-' + lang)
33 | return { isSupported: true, content: Prism.languages[lang] }
34 | }
35 | return { isSupported: true, content: langObject }
36 | } catch (e) {
37 | return { isSupported: false, content: e.message }
38 | }
39 | }
40 |
41 | export function render (code) {
42 | const defaultOption = {
43 | hr: 3
44 | }
45 |
46 | let renderer = new marked.Renderer()
47 |
48 | renderer.hr = () => {
49 | return (
50 | '' +
51 | ` ` +
54 | ' '
55 | )
56 | }
57 |
58 | renderer.heading = (text, level, raw) => {
59 | console.log(`Text: ${text}\nLevel: ${level}\nRaw: ${raw}`)
60 | if (level === 1) {
61 | return `${text} `
62 | }
63 | return `${raw}
`
64 | }
65 |
66 | renderer.code = (code, language, isEscaped) => {
67 | // 4-space codeblock
68 | if (language === undefined) {
69 | return ` ${code}
`
70 | }
71 |
72 | // Others
73 | try {
74 | // shell-like problem
75 | let oriLang = language
76 | if (languages.translate.has(language.toUpperCase())) {
77 | language = languages.translate.get(language.toUpperCase())
78 | } else if (languages.renderName.has(language.toUpperCase())) {
79 | oriLang = languages.renderName.get(language.toUpperCase()).render
80 | language = languages.renderName.get(language.toUpperCase()).ori
81 | }
82 |
83 | let lang = loadPrismLang(language, oriLang)
84 |
85 | if (!lang.isSupported) {
86 | throw new RendererException(lang.content)
87 | }
88 | const rendered = Prism.highlight(code, lang.content)
89 | const dataLang = languages.languagesC.get(oriLang.toUpperCase())
90 |
91 | return (
92 | '' +
93 | `${rendered} ` +
94 | ' '
95 | )
96 | } catch (e) {
97 | return `此段代码块出现渲染错误!不支持语言:${
98 | e.message
99 | }!请检查代码块是否书写正确! `
100 | }
101 | }
102 |
103 | return marked(code, {
104 | renderer: renderer,
105 | gfm: true,
106 | breaks: true,
107 | mangle: false,
108 | silent: true
109 | })
110 | }
111 |
--------------------------------------------------------------------------------
/.electron-vue/build.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | process.env.NODE_ENV = 'production'
4 |
5 | const { say } = require('cfonts')
6 | const chalk = require('chalk')
7 | const del = require('del')
8 | const { spawn } = require('child_process')
9 | const webpack = require('webpack')
10 | const Multispinner = require('multispinner')
11 |
12 |
13 | const mainConfig = require('./webpack.main.config')
14 | const rendererConfig = require('./webpack.renderer.config')
15 | const webConfig = require('./webpack.web.config')
16 |
17 | const doneLog = chalk.bgGreen.white(' DONE ') + ' '
18 | const errorLog = chalk.bgRed.white(' ERROR ') + ' '
19 | const okayLog = chalk.bgBlue.white(' OKAY ') + ' '
20 | const isCI = process.env.CI || false
21 |
22 | if (process.env.BUILD_TARGET === 'clean') clean()
23 | else if (process.env.BUILD_TARGET === 'web') web()
24 | else build()
25 |
26 | function clean () {
27 | del.sync(['build/*', '!build/icons', '!build/icons/icon.*'])
28 | console.log(`\n${doneLog}\n`)
29 | process.exit()
30 | }
31 |
32 | function build () {
33 | greeting()
34 |
35 | del.sync(['dist/electron/*', '!.gitkeep'])
36 |
37 | const tasks = ['main', 'renderer']
38 | const m = new Multispinner(tasks, {
39 | preText: 'building',
40 | postText: 'process'
41 | })
42 |
43 | let results = ''
44 |
45 | m.on('success', () => {
46 | process.stdout.write('\x1B[2J\x1B[0f')
47 | console.log(`\n\n${results}`)
48 | console.log(`${okayLog}take it away ${chalk.yellow('`electron-builder`')}\n`)
49 | process.exit()
50 | })
51 |
52 | pack(mainConfig).then(result => {
53 | results += result + '\n\n'
54 | m.success('main')
55 | }).catch(err => {
56 | m.error('main')
57 | console.log(`\n ${errorLog}failed to build main process`)
58 | console.error(`\n${err}\n`)
59 | process.exit(1)
60 | })
61 |
62 | pack(rendererConfig).then(result => {
63 | results += result + '\n\n'
64 | m.success('renderer')
65 | }).catch(err => {
66 | m.error('renderer')
67 | console.log(`\n ${errorLog}failed to build renderer process`)
68 | console.error(`\n${err}\n`)
69 | process.exit(1)
70 | })
71 | }
72 |
73 | function pack (config) {
74 | return new Promise((resolve, reject) => {
75 | webpack(config, (err, stats) => {
76 | config.mode = 'production'
77 | if (err) reject(err.stack || err)
78 | else if (stats.hasErrors()) {
79 | let err = ''
80 |
81 | stats.toString({
82 | chunks: false,
83 | colors: true
84 | })
85 | .split(/\r?\n/)
86 | .forEach(line => {
87 | err += ` ${line}\n`
88 | })
89 |
90 | reject(err)
91 | } else {
92 | resolve(stats.toString({
93 | chunks: false,
94 | colors: true
95 | }))
96 | }
97 | })
98 | })
99 | }
100 |
101 | function web () {
102 | del.sync(['dist/web/*', '!.gitkeep'])
103 | webpack(webConfig, (err, stats) => {
104 | webConfig.mode = 'production'
105 | if (err || stats.hasErrors()) console.log(err)
106 |
107 | console.log(stats.toString({
108 | chunks: false,
109 | colors: true
110 | }))
111 |
112 | process.exit()
113 | })
114 | }
115 |
116 | function greeting () {
117 | const cols = process.stdout.columns
118 | let text = ''
119 |
120 | if (cols > 85) text = 'lets-build'
121 | else if (cols > 60) text = 'lets-|build'
122 | else text = false
123 |
124 | if (text && !isCI) {
125 | say(text, {
126 | colors: ['yellow'],
127 | font: 'simple3d',
128 | space: false
129 | })
130 | } else console.log(chalk.yellow.bold('\n lets-build'))
131 | console.log()
132 | }
133 |
--------------------------------------------------------------------------------
/.electron-vue/webpack.web.config.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | process.env.BABEL_ENV = 'web'
4 |
5 | const path = require('path')
6 | const webpack = require('webpack')
7 |
8 | const BabiliWebpackPlugin = require('babili-webpack-plugin')
9 | const CopyWebpackPlugin = require('copy-webpack-plugin')
10 | const MiniCssExtractPlugin = require('mini-css-extract-plugin')
11 | const HtmlWebpackPlugin = require('html-webpack-plugin')
12 | const { VueLoaderPlugin } = require('vue-loader')
13 |
14 | let webConfig = {
15 | devtool: '#cheap-module-eval-source-map',
16 | entry: {
17 | web: path.join(__dirname, '../src/renderer/main.js')
18 | },
19 | module: {
20 | rules: [
21 | {
22 | test: /\.(js|vue)$/,
23 | enforce: 'pre',
24 | exclude: /node_modules/,
25 | use: {
26 | loader: 'eslint-loader',
27 | options: {
28 | formatter: require('eslint-friendly-formatter')
29 | }
30 | }
31 | },
32 | {
33 | test: /\.css$/,
34 | use: ['vue-style-loader', 'css-loader']
35 | },
36 | {
37 | test: /\.html$/,
38 | use: 'vue-html-loader'
39 | },
40 | {
41 | test: /\.js$/,
42 | use: 'babel-loader',
43 | include: [ path.resolve(__dirname, '../src/renderer') ],
44 | exclude: /node_modules/
45 | },
46 | {
47 | test: /\.vue$/,
48 | use: {
49 | loader: 'vue-loader',
50 | options: {
51 | extractCSS: true,
52 | loaders: {
53 | sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1',
54 | scss: 'vue-style-loader!css-loader!sass-loader'
55 | }
56 | }
57 | }
58 | },
59 | {
60 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
61 | use: {
62 | loader: 'url-loader',
63 | query: {
64 | limit: 10000,
65 | name: 'imgs/[name].[ext]'
66 | }
67 | }
68 | },
69 | {
70 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
71 | use: {
72 | loader: 'url-loader',
73 | query: {
74 | limit: 10000,
75 | name: 'fonts/[name].[ext]'
76 | }
77 | }
78 | }
79 | ]
80 | },
81 | plugins: [
82 | new VueLoaderPlugin(),
83 | new MiniCssExtractPlugin({filename: 'styles.css'}),
84 | new HtmlWebpackPlugin({
85 | filename: 'index.html',
86 | template: path.resolve(__dirname, '../src/index.ejs'),
87 | minify: {
88 | collapseWhitespace: true,
89 | removeAttributeQuotes: true,
90 | removeComments: true
91 | },
92 | nodeModules: false
93 | }),
94 | new webpack.DefinePlugin({
95 | 'process.env.IS_WEB': 'true'
96 | }),
97 | new webpack.HotModuleReplacementPlugin(),
98 | new webpack.NoEmitOnErrorsPlugin()
99 | ],
100 | output: {
101 | filename: '[name].js',
102 | path: path.join(__dirname, '../dist/web')
103 | },
104 | resolve: {
105 | alias: {
106 | '@': path.join(__dirname, '../src/renderer'),
107 | 'vue$': 'vue/dist/vue.esm.js'
108 | },
109 | extensions: ['.js', '.vue', '.json', '.css']
110 | },
111 | target: 'web'
112 | }
113 |
114 | /**
115 | * Adjust webConfig for production settings
116 | */
117 | if (process.env.NODE_ENV === 'production') {
118 | webConfig.devtool = ''
119 |
120 | webConfig.plugins.push(
121 | new BabiliWebpackPlugin(),
122 | new CopyWebpackPlugin([
123 | {
124 | from: path.join(__dirname, '../static'),
125 | to: path.join(__dirname, '../dist/web/static'),
126 | ignore: ['.*']
127 | }
128 | ]),
129 | new webpack.DefinePlugin({
130 | 'process.env.NODE_ENV': '"production"'
131 | }),
132 | new webpack.LoaderOptionsPlugin({
133 | minimize: true
134 | })
135 | )
136 | }
137 |
138 | module.exports = webConfig
139 |
--------------------------------------------------------------------------------
/src/renderer/store/modules/Passage.js:
--------------------------------------------------------------------------------
1 | import * as fs from 'fs'
2 | import * as path from 'path'
3 | import * as rimraf from 'rimraf'
4 | import * as sharp from 'sharp'
5 | import * as constants from '../../utils/constants'
6 |
7 | const state = {
8 | passageData: new Map(),
9 | passageContent: new Map(),
10 |
11 | currentPassage: {
12 | name: '',
13 | text: ''
14 | }
15 | }
16 |
17 | const mutations = {
18 | // For Editor
19 | SET_CONTENT (state, content) {
20 | state.currentPassage.text = content
21 | },
22 | SET_PASSAGE (state, payload) {
23 | state.currentPassage.name = payload.name
24 |
25 | // TODO: Optimize interface
26 | state.currentPassage.text = state.passageContent.get(payload.name).local
27 | },
28 | RESET_PASSAGE (state) {
29 | state.currentPassage = {
30 | name: '',
31 | text: ''
32 | }
33 | },
34 | SAVE_PASSAGE (state, text) {
35 | // TODO: Save files differently
36 | const content = state.passageContent.get(state.currentPassage.name)
37 | state.passageContent.set(state.currentPassage.name, {
38 | ...content,
39 | local: text
40 | })
41 | fs.writeFileSync(constants.localMDPath(state.currentPassage.name), text, {
42 | encoding: 'utf-8'
43 | })
44 | },
45 |
46 | // Passage Library
47 | NEW_PASSAGE (state, payload) {
48 | fs.mkdirSync(constants.columnPath(payload.name))
49 | fs.mkdirSync(constants.imagePath(payload.name))
50 | fs.mkdirSync(constants.documentPath(payload.name))
51 |
52 | // Save File
53 | fs.writeFileSync(
54 | constants.indexJson(payload.name),
55 | JSON.stringify(payload, undefined, 2),
56 | { encoding: 'utf-8' }
57 | )
58 | // Set local empty
59 | fs.writeFileSync(constants.localMDPath(payload.name), '', {
60 | encoding: 'utf-8'
61 | })
62 |
63 | // Set remote empty
64 | fs.writeFileSync(constants.remoteMDPath(payload.name), '', {
65 | encoding: 'utf-8'
66 | })
67 |
68 | // Copy cover to relative path
69 | sharp(payload.image).toFile(constants.localCoverPath(payload.name))
70 | payload.image = './images/cover.png'
71 |
72 | // Resolve relative path
73 | payload.image = constants.localCoverPath(payload.name)
74 |
75 | state.passageData.set(payload.name, {
76 | // Deep copy payload and add to map
77 | ...JSON.parse(JSON.stringify(payload))
78 | })
79 |
80 | state.passageContent.set(payload.name, {
81 | local: '',
82 | remote: ''
83 | })
84 | },
85 | DEL_PASSAGE (state, payload) {
86 | state.passageData.delete(payload.name)
87 | rimraf.sync(constants.columnPath(payload.name))
88 | },
89 |
90 | LOAD_PASSAGES (state) {
91 | if (!fs.existsSync(constants.PATH)) {
92 | fs.mkdirSync(constants.PATH)
93 | return
94 | }
95 |
96 | const dirStat = fs.readdirSync(constants.PATH)
97 | for (const d of dirStat) {
98 | if (fs.statSync(constants.columnPath(d)).isDirectory()) {
99 | try {
100 | // Load config
101 | const passage = JSON.parse(
102 | fs.readFileSync(
103 | path.resolve(constants.columnPath(d), 'index.json'),
104 | { encoding: 'utf-8' }
105 | )
106 | )
107 | // Load local passage
108 | const local = fs.readFileSync(constants.localMDPath(d), {
109 | encoding: 'utf-8'
110 | })
111 | // Load remote passage
112 | const remote = fs.readFileSync(constants.remoteMDPath(d), {
113 | encoding: 'utf-8'
114 | })
115 | // Load cover
116 | passage.image =
117 | passage.image[0] === '.'
118 | ? constants.localCoverPath(passage.name)
119 | : passage.image
120 |
121 | // Add to map
122 | state.passageData.set(d, passage)
123 | state.passageContent.set(d, {
124 | local: local,
125 | remote: remote
126 | })
127 | } catch (e) {
128 | console.error(e.message)
129 | }
130 | }
131 | }
132 | }
133 | }
134 |
135 | export default {
136 | state,
137 | mutations
138 | }
139 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | ## [0.1.4-180822](https://github.com/Yesterday17/Bilibili-Column-Helper/compare/v0.1.3-180814...v0.1.4-180822) (2018-08-22)
3 |
4 |
5 | ### Bug Fixes
6 |
7 | * renderer can only render \ now ([3798808](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/3798808))
8 |
9 |
10 | ### Features
11 |
12 | * save file at a relative path & transform to png format ([0edee84](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/0edee84))
13 |
14 |
15 |
16 |
17 | ## 0.0.1-SNAPSHOT (2018-08-07)
18 |
19 |
20 | ### Bug Fixes
21 |
22 | * **code:** fix tab switch ([730ce18](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/730ce18))
23 | * fix wrongly displayed header ([8a8cb1f](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/8a8cb1f))
24 | * **code:** make devtools enabled with F8 ([4c455a1](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/4c455a1))
25 | * disable commitlint on ci ([626ec27](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/626ec27))
26 | * fix codemirror display differently in dev and release ([8be971a](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/8be971a)), closes [#4](https://github.com/Yesterday17/Bilibili-Column-Helper/issues/4)
27 | * **code:** remove passage to make sure passage is empty by deafult ([e01a61a](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/e01a61a))
28 | * fix not saving after deleting a passage ([f20952e](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/f20952e))
29 | * fix object.assign shallow copy problem and save passages to file ([3530639](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/3530639))
30 | * fix overriding text of the previous edition ([4c55a2d](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/4c55a2d))
31 | * fix required category not essential ([923a6cf](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/923a6cf))
32 | * fix the wrong display of the main window border ([40311e8](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/40311e8))
33 | * make it a must to write the title and type of a column ([3d0201b](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/3d0201b))
34 | * make the whole form cleared when closing the dialog ([e521561](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/e521561))
35 |
36 |
37 | ### Features
38 |
39 | * **code:** add developer tool shortcut ([d8d3cf8](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/d8d3cf8))
40 | * **code:** add unit test ([051ed41](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/051ed41))
41 | * add passage tag ([1d1b455](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/1d1b455))
42 | * **code:** update to the latest electron-vue ([aa16011](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/aa16011))
43 | * add information increasement ([d8387c4](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/d8387c4))
44 | * add subtype to meet bilibili's category ([0666c07](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/0666c07))
45 | * close editing ([39bc040](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/39bc040))
46 | * default poster ([2fab19e](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/2fab19e))
47 | * get category list online ([20b9e5d](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/20b9e5d))
48 | * hide editor page default ([92ba068](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/92ba068))
49 | * import vue-devtool to project ([62070bc](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/62070bc))
50 | * link to appveyor ([9cfa1aa](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/9cfa1aa))
51 | * **style:** add commitlint to generate changelog and regulate commit ([a398444](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/a398444))
52 | * make category a dedicated part which can sync with server ([f7b3d82](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/f7b3d82))
53 | * make codemirror fulfill the whole layout ([ce8b6d8](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/ce8b6d8))
54 | * make column passages sorted by time ([4b90a52](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/4b90a52))
55 | * save file automatically ([c5e0b56](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/c5e0b56))
56 | * simple poster logic ([4189185](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/4189185))
57 | * support login ([269c39d](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/269c39d))
58 | * upload image by paste ([5cdc5e4](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/5cdc5e4))
59 | * users can logout now ([f1ce5a1](https://github.com/Yesterday17/Bilibili-Column-Helper/commit/f1ce5a1))
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/src/renderer/components/Setting.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | 专栏设置
16 |
17 |
18 | 渲染器:
19 |
20 |
21 |
22 |
23 |
24 |
25 | 推送器:
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | 同步设置
35 |
36 |
37 | 其他设置
38 |
39 |
40 |
41 |
42 |
118 |
119 |
--------------------------------------------------------------------------------
/src/renderer/components/Editor.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 | {{code}}
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
103 |
104 |
--------------------------------------------------------------------------------
/.electron-vue/dev-runner.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const chalk = require('chalk')
4 | const electron = require('electron')
5 | const path = require('path')
6 | const { say } = require('cfonts')
7 | const { spawn } = require('child_process')
8 | const webpack = require('webpack')
9 | const WebpackDevServer = require('webpack-dev-server')
10 | const webpackHotMiddleware = require('webpack-hot-middleware')
11 |
12 | const mainConfig = require('./webpack.main.config')
13 | const rendererConfig = require('./webpack.renderer.config')
14 |
15 | let electronProcess = null
16 | let manualRestart = false
17 | let hotMiddleware
18 |
19 | function logStats (proc, data) {
20 | let log = ''
21 |
22 | log += chalk.yellow.bold(`┏ ${proc} Process ${new Array((19 - proc.length) + 1).join('-')}`)
23 | log += '\n\n'
24 |
25 | if (typeof data === 'object') {
26 | data.toString({
27 | colors: true,
28 | chunks: false
29 | }).split(/\r?\n/).forEach(line => {
30 | log += ' ' + line + '\n'
31 | })
32 | } else {
33 | log += ` ${data}\n`
34 | }
35 |
36 | log += '\n' + chalk.yellow.bold(`┗ ${new Array(28 + 1).join('-')}`) + '\n'
37 |
38 | console.log(log)
39 | }
40 |
41 | function startRenderer () {
42 | return new Promise((resolve, reject) => {
43 | rendererConfig.entry.renderer = [path.join(__dirname, 'dev-client')].concat(rendererConfig.entry.renderer)
44 | rendererConfig.mode = 'development'
45 |
46 | const compiler = webpack(rendererConfig)
47 | hotMiddleware = webpackHotMiddleware(compiler, {
48 | log: false,
49 | heartbeat: 2500
50 | })
51 | compiler.hooks.compilation.tap('compilation', compilation => {
52 | compilation.hooks.htmlWebpackPluginAfterEmit.tapAsync('html-webpack-plugin-after-emit', (data, cb) => {
53 | hotMiddleware.publish({ action: 'reload' })
54 | cb()
55 | })
56 | })
57 |
58 | compiler.hooks.done.tap('done', stats => {
59 | logStats('Renderer', stats)
60 | })
61 |
62 | const server = new WebpackDevServer(
63 | compiler,
64 | {
65 | contentBase: path.join(__dirname, '../'),
66 | quiet: true,
67 | before (app, ctx) {
68 | app.use(hotMiddleware)
69 | ctx.middleware.waitUntilValid(() => {
70 | resolve()
71 | })
72 | }
73 | }
74 | )
75 |
76 | server.listen(9080)
77 | })
78 | }
79 |
80 | function startMain () {
81 | return new Promise((resolve, reject) => {
82 | mainConfig.entry.main = [path.join(__dirname, '../src/main/index.dev.js')].concat(mainConfig.entry.main)
83 | mainConfig.mode = 'development'
84 |
85 | const compiler = webpack(mainConfig)
86 |
87 | compiler.hooks.watchRun.tapAsync('watch-run', (compilation, done) => {
88 | logStats('Main', chalk.white.bold('compiling...'))
89 | hotMiddleware.publish({ action: 'compiling' })
90 | done()
91 | })
92 |
93 | compiler.watch({}, (err, stats) => {
94 | if (err) {
95 | console.log(err)
96 | return
97 | }
98 |
99 | logStats('Main', stats)
100 |
101 | if (electronProcess && electronProcess.kill) {
102 | manualRestart = true
103 | process.kill(electronProcess.pid)
104 | electronProcess = null
105 | startElectron()
106 |
107 | setTimeout(() => {
108 | manualRestart = false
109 | }, 5000)
110 | }
111 |
112 | resolve()
113 | })
114 | })
115 | }
116 |
117 | function startElectron () {
118 | electronProcess = spawn(electron, ['--inspect=5858', path.join(__dirname, '../dist/electron/main.js')])
119 |
120 | electronProcess.stdout.on('data', data => {
121 | electronLog(data, 'blue')
122 | })
123 | electronProcess.stderr.on('data', data => {
124 | electronLog(data, 'red')
125 | })
126 |
127 | electronProcess.on('close', () => {
128 | if (!manualRestart) process.exit()
129 | })
130 | }
131 |
132 | function electronLog (data, color) {
133 | let log = ''
134 | data = data.toString().split(/\r?\n/)
135 | data.forEach(line => {
136 | log += ` ${line}\n`
137 | })
138 | if (/[0-9A-z]+/.test(log)) {
139 | console.log(
140 | chalk[color].bold('┏ Electron -------------------') +
141 | '\n\n' +
142 | log +
143 | chalk[color].bold('┗ ----------------------------') +
144 | '\n'
145 | )
146 | }
147 | }
148 |
149 | function greeting () {
150 | const cols = process.stdout.columns
151 | let text = ''
152 |
153 | if (cols > 104) text = 'electron-vue'
154 | else if (cols > 76) text = 'electron-|vue'
155 | else text = false
156 |
157 | if (text) {
158 | say(text, {
159 | colors: ['yellow'],
160 | font: 'simple3d',
161 | space: false
162 | })
163 | } else console.log(chalk.yellow.bold('\n electron-vue'))
164 | console.log(chalk.blue(' getting ready...') + '\n')
165 | }
166 |
167 | function init () {
168 | greeting()
169 |
170 | Promise.all([startRenderer(), startMain()])
171 | .then(() => {
172 | startElectron()
173 | })
174 | .catch(err => {
175 | console.error(err)
176 | })
177 | }
178 |
179 | init()
180 |
--------------------------------------------------------------------------------
/.electron-vue/webpack.renderer.config.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | process.env.BABEL_ENV = 'renderer'
4 |
5 | const path = require('path')
6 | const { dependencies } = require('../package.json')
7 | const webpack = require('webpack')
8 |
9 | const BabiliWebpackPlugin = require('babili-webpack-plugin')
10 | const CopyWebpackPlugin = require('copy-webpack-plugin')
11 | const MiniCssExtractPlugin = require('mini-css-extract-plugin')
12 | const HtmlWebpackPlugin = require('html-webpack-plugin')
13 | const { VueLoaderPlugin } = require('vue-loader')
14 |
15 | /**
16 | * List of node_modules to include in webpack bundle
17 | *
18 | * Required for specific packages like Vue UI libraries
19 | * that provide pure *.vue files that need compiling
20 | * https://simulatedgreg.gitbooks.io/electron-vue/content/en/webpack-configurations.html#white-listing-externals
21 | */
22 | let whiteListedModules = ['vue']
23 |
24 | let rendererConfig = {
25 | devtool: '#cheap-module-eval-source-map',
26 | entry: {
27 | renderer: path.join(__dirname, '../src/renderer/main.js')
28 | },
29 | externals: [
30 | ...Object.keys(dependencies || {}).filter(
31 | d => !whiteListedModules.includes(d)
32 | )
33 | ],
34 | module: {
35 | rules: [
36 | {
37 | test: /\.(js|vue)$/,
38 | enforce: 'pre',
39 | exclude: /node_modules/,
40 | use: {
41 | loader: 'eslint-loader',
42 | options: {
43 | formatter: require('eslint-friendly-formatter')
44 | }
45 | }
46 | },
47 | {
48 | test: /\.css$/,
49 | use: ['vue-style-loader', 'css-loader']
50 | },
51 | {
52 | test: /\.html$/,
53 | use: 'vue-html-loader'
54 | },
55 | {
56 | test: /\.js$/,
57 | use: 'babel-loader',
58 | exclude: /node_modules/
59 | },
60 | {
61 | test: /\.node$/,
62 | use: 'node-loader'
63 | },
64 | {
65 | test: /\.vue$/,
66 | use: {
67 | loader: 'vue-loader',
68 | options: {
69 | extractCSS: process.env.NODE_ENV === 'production',
70 | loaders: {
71 | sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1',
72 | scss: 'vue-style-loader!css-loader!sass-loader'
73 | }
74 | }
75 | }
76 | },
77 | {
78 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
79 | use: {
80 | loader: 'url-loader',
81 | query: {
82 | limit: 10000,
83 | name: 'imgs/[name]--[folder].[ext]'
84 | }
85 | }
86 | },
87 | {
88 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
89 | loader: 'url-loader',
90 | options: {
91 | limit: 10000,
92 | name: 'media/[name]--[folder].[ext]'
93 | }
94 | },
95 | {
96 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
97 | use: {
98 | loader: 'url-loader',
99 | query: {
100 | limit: 10000,
101 | name: 'fonts/[name]--[folder].[ext]'
102 | }
103 | }
104 | }
105 | ]
106 | },
107 | node: {
108 | __dirname: process.env.NODE_ENV !== 'production',
109 | __filename: process.env.NODE_ENV !== 'production'
110 | },
111 | plugins: [
112 | new VueLoaderPlugin(),
113 | new MiniCssExtractPlugin({filename: 'styles.css'}),
114 | new HtmlWebpackPlugin({
115 | filename: 'index.html',
116 | template: path.resolve(__dirname, '../src/index.ejs'),
117 | minify: {
118 | collapseWhitespace: true,
119 | removeAttributeQuotes: true,
120 | removeComments: true
121 | },
122 | nodeModules:
123 | process.env.NODE_ENV !== 'production'
124 | ? path.resolve(__dirname, '../node_modules')
125 | : false
126 | }),
127 | new webpack.HotModuleReplacementPlugin()
128 | ],
129 | output: {
130 | filename: '[name].js',
131 | libraryTarget: 'commonjs2',
132 | path: path.join(__dirname, '../dist/electron')
133 | },
134 | resolve: {
135 | alias: {
136 | '@': path.join(__dirname, '../src/renderer'),
137 | 'vue$': 'vue/dist/vue.esm.js'
138 | },
139 | extensions: ['.js', '.vue', '.json', '.css', '.node']
140 | },
141 | target: 'electron-renderer'
142 | }
143 |
144 | /**
145 | * Adjust rendererConfig for development settings
146 | */
147 | if (process.env.NODE_ENV !== 'production') {
148 | rendererConfig.plugins.push(
149 | new webpack.DefinePlugin({
150 | '__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"`
151 | })
152 | )
153 | }
154 |
155 | /**
156 | * Adjust rendererConfig for production settings
157 | */
158 | if (process.env.NODE_ENV === 'production') {
159 | rendererConfig.devtool = ''
160 |
161 | rendererConfig.plugins.push(
162 | new BabiliWebpackPlugin(),
163 | new CopyWebpackPlugin([
164 | {
165 | from: path.join(__dirname, '../static'),
166 | to: path.join(__dirname, '../dist/electron/static'),
167 | ignore: ['.*']
168 | }
169 | ]),
170 | new webpack.LoaderOptionsPlugin({
171 | minimize: true
172 | })
173 | )
174 | }
175 |
176 | module.exports = rendererConfig
177 |
--------------------------------------------------------------------------------
/src/renderer/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | 专栏管理
27 |
28 |
29 |
30 | Markdown 编辑器
31 |
32 |
33 |
34 | 设置
35 |
36 |
37 |
38 | 关于
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
122 |
123 |
219 |
--------------------------------------------------------------------------------
/src/renderer/components/subcomponents/Passage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
{{$store.state.Sync.categoryMap.get(props.category)}}
13 |
{{props.name}}
14 |
15 |
16 |
17 |
文章标签:
18 |
{{item}}
19 |
20 |
最后修改时间: {{new Date(props.pubdate).toLocaleString("zh-CN", {hour12: false})}}
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
105 |
106 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bilibili-column-helper",
3 | "version": "0.1.4-180822",
4 | "author": "Yesterday17 ",
5 | "description": "Transfers markdown to bilibili column passage. Using Electron & Marked.",
6 | "homepage": "https://github.com/Yesterday17/Bilibili-Column-Helper/",
7 | "license": "MIT",
8 | "main": "./dist/electron/main.js",
9 | "scripts": {
10 | "rebuild": "./node_modules/.bin/electron-rebuild",
11 | "dist": "node .electron-vue/build.js && electron-builder --publish always",
12 | "distRelease": "node .electron-vue/build.js && electron-builder --publish onTagOrDraft",
13 | "build": "node .electron-vue/build.js && electron-builder",
14 | "build:dir": "node .electron-vue/build.js && electron-builder --dir",
15 | "build:clean": "cross-env BUILD_TARGET=clean node .electron-vue/build.js",
16 | "build:web": "cross-env BUILD_TARGET=web node .electron-vue/build.js",
17 | "dev": "node .electron-vue/dev-runner.js",
18 | "e2e": "npm run pack && mocha test/e2e",
19 | "lint": "eslint --ext .js,.vue -f ./node_modules/eslint-friendly-formatter src test",
20 | "lint:fix": "eslint --ext .js,.vue -f ./node_modules/eslint-friendly-formatter --fix src test",
21 | "pack": "npm run pack:main && npm run pack:renderer",
22 | "pack:main": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.main.config.js",
23 | "pack:renderer": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.renderer.config.js",
24 | "test": "npm run unit && npm run e2e",
25 | "unit": "karma start test/unit/karma.conf.js",
26 | "postinstall": "npm run lint:fix && electron-builder install-app-deps",
27 | "commitmsg": "commitlint -e $GIT_PARAMS",
28 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s"
29 | },
30 | "build": {
31 | "productName": "哔哩哔哩专栏助手",
32 | "appId": "cn.yesterday17.bilibili-column-helper",
33 | "directories": {
34 | "output": "build"
35 | },
36 | "files": [
37 | "dist/electron/**/*"
38 | ],
39 | "dmg": {
40 | "contents": [
41 | {
42 | "x": 410,
43 | "y": 150,
44 | "type": "link",
45 | "path": "/Applications"
46 | },
47 | {
48 | "x": 130,
49 | "y": 150,
50 | "type": "file"
51 | }
52 | ]
53 | },
54 | "mac": {
55 | "icon": "build/icons/icon.icns",
56 | "category": "public.app-category.utilities"
57 | },
58 | "win": {
59 | "icon": "build/icons/icon.png",
60 | "target": [
61 | "nsis",
62 | "portable",
63 | "zip"
64 | ]
65 | },
66 | "linux": {
67 | "icon": "build/icons",
68 | "category": "Utility",
69 | "target": [
70 | "deb",
71 | "tar.gz",
72 | "AppImage"
73 | ]
74 | }
75 | },
76 | "dependencies": {
77 | "bilibili-zhuanlan-markdown-tool": "^1.0.2",
78 | "electron-store": "^2.0.0",
79 | "element-ui": "^2.4.0",
80 | "marked": "^0.4.0",
81 | "prismjs": "^1.15.0",
82 | "request": "^2.83.0",
83 | "request-promise": "^4.2.2",
84 | "rimraf": "^2.6.2",
85 | "sharp": "^0.20.7",
86 | "vue": "^2.5.16",
87 | "vue-codemirror-electron": "^3.0.7",
88 | "vue-electron": "^1.0.6",
89 | "vue-router": "^3.0.1",
90 | "vuex": "^3.0.1"
91 | },
92 | "devDependencies": {
93 | "@commitlint/cli": "^7.0.0",
94 | "@commitlint/config-conventional": "^7.0.1",
95 | "axios": "^0.18.0",
96 | "babel-core": "^6.25.0",
97 | "babel-eslint": "^8.2.6",
98 | "babel-loader": "^7.1.1",
99 | "babel-plugin-istanbul": "^4.1.1",
100 | "babel-plugin-transform-runtime": "^6.23.0",
101 | "babel-preset-env": "^1.6.0",
102 | "babel-preset-stage-0": "^6.24.1",
103 | "babel-register": "^6.24.1",
104 | "babili-webpack-plugin": "^0.1.2",
105 | "cfonts": "^2.1.3",
106 | "chai": "^4.0.0",
107 | "chalk": "^2.1.0",
108 | "codemirror": "^5.35.0",
109 | "commitlint": "^7.0.0",
110 | "copy-webpack-plugin": "^4.0.1",
111 | "cross-env": "^5.0.5",
112 | "css-loader": "^1.0.0",
113 | "del": "^3.0.0",
114 | "devtron": "^1.4.0",
115 | "electron": "^2.0.6",
116 | "electron-builder": "^20.27.1",
117 | "electron-debug": "^2.0.0",
118 | "electron-devtools-installer": "^2.2.4",
119 | "electron-rebuild": "^1.8.2",
120 | "eslint": "^5.3.0",
121 | "eslint-config-standard": "^11.0.0",
122 | "eslint-friendly-formatter": "^4.0.1",
123 | "eslint-loader": "^2.1.0",
124 | "eslint-plugin-html": "^4.0.5",
125 | "eslint-plugin-import": "^2.7.0",
126 | "eslint-plugin-node": "^7.0.1",
127 | "eslint-plugin-promise": "^3.5.0",
128 | "eslint-plugin-standard": "^3.1.0",
129 | "file-loader": "^1.1.11",
130 | "glob": "^7.1.2",
131 | "html-webpack-plugin": "^3.2.0",
132 | "husky": "^0.14.3",
133 | "inject-loader": "^4.0.1",
134 | "karma": "^2.0.5",
135 | "karma-chai": "^0.1.0",
136 | "karma-coverage": "^1.1.1",
137 | "karma-electron": "^6.0.0",
138 | "karma-mocha": "^1.2.0",
139 | "karma-sourcemap-loader": "^0.3.7",
140 | "karma-spec-reporter": "^0.0.32",
141 | "karma-webpack": "^3.0.0",
142 | "mini-css-extract-plugin": "0.4.0",
143 | "mocha": "^5.2.0",
144 | "multispinner": "^0.2.1",
145 | "node-loader": "^0.6.0",
146 | "require-dir": "^1.0.0",
147 | "spectron": "^3.7.1",
148 | "style-loader": "^0.22.1",
149 | "url-loader": "^1.0.1",
150 | "vue-codemirror": "^4.0.4",
151 | "vue-html-loader": "^1.2.4",
152 | "vue-loader": "^15.3.0",
153 | "vue-style-loader": "^4.1.1",
154 | "vue-template-compiler": "^2.4.2",
155 | "webpack": "^4.16.5",
156 | "webpack-cli": "^3.1.0",
157 | "webpack-dev-server": "^3.1.5",
158 | "webpack-hot-middleware": "^2.18.2",
159 | "webpack-merge": "^4.1.0"
160 | },
161 | "__npminstall_done": false
162 | }
163 |
--------------------------------------------------------------------------------
/src/renderer/store/modules/Sync.js:
--------------------------------------------------------------------------------
1 | import Store from 'electron-store'
2 | import * as biliNetwork from '../../utils/biliNetwork'
3 |
4 | let sync = new Store({
5 | name: 'sync'
6 | })
7 |
8 | const defaults = {
9 | category: [
10 | {
11 | id: 2,
12 | parent_id: 0,
13 | name: '动画',
14 | children: [
15 | {
16 | id: 4,
17 | parent_id: 2,
18 | name: '动漫杂谈'
19 | },
20 | {
21 | id: 5,
22 | parent_id: 2,
23 | name: '动漫资讯'
24 | },
25 | {
26 | id: 31,
27 | parent_id: 2,
28 | name: '动画技术'
29 | }
30 | ]
31 | },
32 | {
33 | id: 1,
34 | parent_id: 0,
35 | name: '游戏',
36 | children: [
37 | {
38 | id: 6,
39 | parent_id: 1,
40 | name: '单机游戏'
41 | },
42 | {
43 | id: 7,
44 | parent_id: 1,
45 | name: '电子竞技'
46 | },
47 | {
48 | id: 8,
49 | parent_id: 1,
50 | name: '手机游戏'
51 | },
52 | {
53 | id: 9,
54 | parent_id: 1,
55 | name: '网络游戏'
56 | },
57 | {
58 | id: 10,
59 | parent_id: 1,
60 | name: '桌游棋牌'
61 | }
62 | ]
63 | },
64 | {
65 | id: 28,
66 | parent_id: 0,
67 | name: '影视',
68 | children: [
69 | {
70 | id: 12,
71 | parent_id: 28,
72 | name: '电影'
73 | },
74 | {
75 | id: 35,
76 | parent_id: 28,
77 | name: '电视剧'
78 | },
79 | {
80 | id: 36,
81 | parent_id: 28,
82 | name: '纪录片'
83 | },
84 | {
85 | id: 37,
86 | parent_id: 28,
87 | name: '综艺'
88 | }
89 | ]
90 | },
91 | {
92 | id: 3,
93 | parent_id: 0,
94 | name: '生活',
95 | children: [
96 | {
97 | id: 13,
98 | parent_id: 3,
99 | name: '美食'
100 | },
101 | {
102 | id: 21,
103 | parent_id: 3,
104 | name: '萌宠'
105 | },
106 | {
107 | id: 14,
108 | parent_id: 3,
109 | name: '时尚'
110 | },
111 | {
112 | id: 22,
113 | parent_id: 3,
114 | name: '运动'
115 | },
116 | {
117 | id: 15,
118 | parent_id: 3,
119 | name: '日常'
120 | }
121 | ]
122 | },
123 | {
124 | id: 29,
125 | parent_id: 0,
126 | name: '兴趣',
127 | children: [
128 | {
129 | id: 23,
130 | parent_id: 29,
131 | name: '绘画'
132 | },
133 | {
134 | id: 24,
135 | parent_id: 29,
136 | name: '手工'
137 | },
138 | {
139 | id: 38,
140 | parent_id: 29,
141 | name: '摄影'
142 | },
143 | {
144 | id: 39,
145 | parent_id: 29,
146 | name: '音乐舞蹈'
147 | },
148 | {
149 | id: 11,
150 | parent_id: 29,
151 | name: '模型手办'
152 | }
153 | ]
154 | },
155 | {
156 | id: 16,
157 | parent_id: 0,
158 | name: '轻小说',
159 | children: [
160 | {
161 | id: 18,
162 | parent_id: 16,
163 | name: '原创连载'
164 | },
165 | {
166 | id: 19,
167 | parent_id: 16,
168 | name: '同人连载'
169 | },
170 | {
171 | id: 32,
172 | parent_id: 16,
173 | name: '短篇小说'
174 | },
175 | {
176 | id: 20,
177 | parent_id: 16,
178 | name: '小说杂谈'
179 | }
180 | ]
181 | },
182 | {
183 | id: 17,
184 | parent_id: 0,
185 | name: '科技',
186 | children: [
187 | {
188 | id: 25,
189 | parent_id: 17,
190 | name: '人文历史'
191 | },
192 | {
193 | id: 33,
194 | parent_id: 17,
195 | name: '自然'
196 | },
197 | {
198 | id: 26,
199 | parent_id: 17,
200 | name: '数码'
201 | },
202 | {
203 | id: 27,
204 | parent_id: 17,
205 | name: '汽车'
206 | },
207 | {
208 | id: 34,
209 | parent_id: 17,
210 | name: '学习'
211 | }
212 | ]
213 | }
214 | ]
215 | }
216 |
217 | const state = {
218 | category: [],
219 | categoryList: [],
220 | categoryMap: new Map(),
221 |
222 | count: {
223 | view: 0,
224 | reply: 0,
225 | like: 0,
226 | coin: 0,
227 | fav: 0,
228 |
229 | incr_view: 0,
230 | incr_reply: 0,
231 | incr_like: 0,
232 | incr_coin: 0,
233 | incr_fav: 0
234 | }
235 | }
236 |
237 | const mutations = {
238 | LOAD_SYNC_CONFIG (state) {
239 | state.category = sync.get('category', defaults.category)
240 |
241 | for (const c of state.category) {
242 | state.categoryMap.set(c.id, c.name)
243 | state.categoryList.push(c.id)
244 |
245 | for (const cd of c.children) {
246 | state.categoryMap.set(cd.id, cd.name)
247 | }
248 | }
249 | },
250 | SAVE_SYNC_CONFIG (state) {
251 | sync.set('category', state.category)
252 | },
253 | UPDATE_USERINFO (state, result) {
254 | state.count.view = result['view']
255 | state.count.reply = result['reply']
256 | state.count.like = result['like']
257 | state.count.coin = result['coin']
258 | state.count.fav = result['fav']
259 | state.count.share = result['share']
260 |
261 | state.count.incr_view = result['incr_view']
262 | state.count.incr_reply = result['incr_reply']
263 | state.count.incr_like = result['incr_like']
264 | state.count.incr_coin = result['incr_coin']
265 | state.count.incr_fav = result['incr_fav']
266 | state.count.incr_share = result['incr_share']
267 | }
268 | }
269 |
270 | const actions = {
271 | SYNC_CONFIG ({ commit }, cookie) {
272 | // TODO: Sync category here.
273 | // state.category
274 |
275 | biliNetwork.getUserInfo(cookie).then(result => {
276 | if (result !== undefined) {
277 | commit('UPDATE_USERINFO', result)
278 | }
279 | })
280 | }
281 | }
282 |
283 | export default {
284 | state,
285 | mutations,
286 | actions
287 | }
288 |
--------------------------------------------------------------------------------
/src/renderer/components/Passages.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 新建专栏
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | -
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
167 |
168 |
--------------------------------------------------------------------------------
/src/renderer/components/About.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
Bilibili Column Helper - Bilibili 专栏助手
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
原理
19 |
本程序以 Electron、Vue.js、Marked 以及 CodeMirror 为主要组件编写,旨在以 Markdown 书写目前并不支持 Markdown 的 Bilibili 专栏。 从原理来看,本程序将要实现的是将 Bilibili 支持的 HTML 特性以原本的方式渲染;而对于不支持的特性(比如表格等),则进行图片的渲染,以达到相同的显示目的。
20 |
用户隐私
21 |
本程序通过 Bilibili 提供的 Ajax 登录界面,实现 Bilibili 账户的登录。账户的使用仅限图片的上传以及专栏内容的上传。
22 |
合作开发(Contribution)
23 |
本工程基于
24 | electron-vue开发,其有相对完善的
25 | 中文文档 可供参考。 前端框架使用的是
26 | Vue.js,文档
27 | 点此访问 。 UI 使用的是
28 | Element,文档
29 | 点此访问 。 以及
30 | Electron的文档:
31 | 点此访问 。
32 |
构建过程
33 |
构建基于 yarn,如果没有安装 yarn 的话就需要执行第一步。在部分系统下(如 Ubuntu 等)使用
34 | npm install -g时需要带上
35 | sudo。
36 |
npm install -g yarn
37 | yarn install
38 |
39 |
如果在上述过程中遇到 electron 无法下载,可以选择使用
40 | cnpm或
41 | npm过渡:
42 |
cnpm install
43 |
44 |
然后就可以通过以下步骤运行:
45 |
yarn dev
46 |
47 |
如果需要打包,则需要运行:
48 |
yarn run build
49 |
50 |
Credits
51 |
52 | Bilibili zhuanlan Markdown-Tool
53 |
54 |
Icons made by
55 | Freepik from
56 | www.flaticon.com is licensed by
57 | Creative Commons BY 3.0 .
58 |
59 |
60 |
61 |
62 |
您只有无条件同意《哔哩哔哩使用协议》及以下《哔哩哔哩专栏区内容上传协议》,才能在哔哩哔哩网的文章分区投稿。
63 |
一、特别提示
64 |
1.1 哔哩哔哩同意按照《哔哩哔哩使用协议》及本协议的规定及其不时发布的操作规则提供基于互联网的相关服务(以下称"网络服务"),为获得网络服务,服务使用人(以下称"用户")同意本协议的全部条款并按照页面上的提示完成全部的注册程序。用户在进行注册程序过程中点击"同意"按钮即表示用户完全接受《哔哩哔哩使用协议》及本声明项下的全部条款。这些条款可由哔哩哔哩域名所有者随时更新,本服务协议一旦发生变动,哔哩哔哩将会在相关的页面上提示修改内容。修改后的服务协议一旦在页面上公布即有效代替原来的服务协议。用户可随时造访查阅最新服务协议。用户在使用哔哩哔哩提供的各项服务之前,应仔细阅读本服务协议,如用户不同意本服务协议及/或随时对其的修改,用户可以主动取消哔哩哔哩提供的服务。
65 |
1.2 哔哩哔哩作为信息分享、交流的服务平台,为用户提供原创信息的信息存储空间服务,用户应合法、有权的使用哔哩哔哩发表信息并单独对此承担法律责任。
66 |
1.3 用户承诺不得以任何方式使用哔哩哔哩直接或间接从事违反中华人民共和国相关法律规定及社会公序良俗的行为,用户不得使用哔哩哔哩服务制作、复制、上载、发布、展示或以其它方式传播含有下列内容之一的信息:
67 |
(1)反对宪法所确定的基本原则的;
68 |
(2)危害国家安全,泄露国家秘密,颠覆国家政权,破坏国家统一的;
69 |
(3)损害国家荣誉和利益的;
70 |
(4)煽动民族仇恨、民族歧视,破坏民族团结的;
71 |
(5)破坏国家宗教政策,宣扬邪教和封建迷信的;
72 |
(6)散布谣言,扰乱社会秩序,破坏社会稳定的;
73 |
(7)散布淫秽、色情、赌博、暴力、凶杀、恐怖或者教唆犯罪的;
74 |
(8)侮辱或者诽谤他人,侵害他人合法权益的;
75 |
(10)含有法律、行政法规禁止的其他内容的信息。
76 |
二、版权声明
77 |
2.1 哔哩哔哩作为信息分享、交流的服务平台,尊重和鼓励用户原创内容,打造基于创作的文化原创社区。同时,哔哩哔哩也尊重任何第三方的合法权益。用户在使用哔哩哔哩发表信息时,不得以任何方式侵害任何第三方的合法权益,包括但不限于著作权、商标权、专利权、姓名权、隐私权等。
78 |
2.2 用户使用哔哩哔哩发表的全部原创内容(包括但不限于文章、图片、视频等),其知识产权归用户所有。
79 |
2.3 哔哩哔哩不会对用户上传的作品内容作任何形式的编辑修改。
80 |
2.4 用户使用哔哩哔哩发表的信息,除非用户明确允许转载的,禁止任何第三方转载或者摘编(用户使用官方“生成图片”功能分享的除外);若该用户允许第三方转载或摘编信息至哔哩哔哩之外的平台,应在转载内容的显著位置注明原作者姓名(或笔名、哔哩哔哩用户昵称),注明内容来源于哔哩哔哩且附有原始链接,并不对转载内容进行修改或演绎。
81 |
2.5 对于用户使用哔哩哔哩发表的信息,若有相关权利人提出关于侵害著作权等合法权益的投诉,哔哩哔哩有权根据法律规定的要求删除相关信息。
82 |
83 |
84 |
85 |
86 |
欢迎各位使用Bilibili专栏,为了保证Bilibili专栏的内容质量,维护专栏的内容生态,让创作者和读者都拥有良好的使用体验和阅读体验,请各位谨遵以下规范条例:
87 |
严令禁止条例
88 |
bilibili严格遵守我国政府颁布的《互联网信息服务管理办法》第十五条规定,并将此作为bilibili平台运行的基本准则;对于含有以下内容的信息,我们将采用最严格的管理方法,予以杜绝:
89 |
(一)反对宪法所确定的基本原则的;
90 |
(二)危害国家安全,泄露国家秘密,颠覆国家政权,破坏国家统一的;
91 |
(三)损害国家荣誉和利益的;
92 |
(四)煽动民族仇恨、民族歧视,破坏民族团结的;
93 |
(五)破坏国家宗教政策,宣扬邪教和封建迷信的;
94 |
(六)散布谣言,扰乱社会秩序,破坏社会稳定的;
95 |
(七)散布淫秽、色情、赌博、暴力、凶杀、恐怖或者教唆犯罪的;
96 |
(八)侮辱或者诽谤他人,侵害他们合法权益的;
97 |
(九)含有法律、行政法规禁止的其他内容的。
98 |
一般违禁条例
99 |
为了保护用户创造的内容、维护良好的社区氛围,我们会对以下的行为进行处理,对作出以下行为的用户进行警告或处罚。
100 |
一、含有裸露和色情内容
101 |
文章中不允许含有性暗示类型的露骨内容,如色情描写、露点图片等。含有怪癖内容的文章,将会被删除或施加限制,具体取决于行为的严重程度。
102 |
禁止在文章及评论中发布与色情内容有关的第三方网址、社交账号、网盘代码等违规信息,一经发现,我们将对发布此类垃圾信息的账号永久封禁。
103 |
二、侵犯个人隐私
104 |
文章内容涉嫌跟踪、威胁、骚扰、胁迫、侵犯用户个人隐私、披露用户个人信息等情况,将会受到严肃处理。对于情节严重的用户,其账号将被永久封禁。
105 |
三、恶意冒充他人
106 |
禁止通过自己的账号信息(昵称、头像、签名、个人空间等),恶意模仿特定用户。另外,伪装成涉及官方业务的账号,同样也是不允许的,已对其他用户造成误导的,将受到相应的处罚。
107 |
四、欺诈、诈骗等行为
108 |
所有通过欺骗他人,为自己谋取经济利益的行为都是不允许的。我们会对此类内容进行删除,特定情况下会对发布者发出警示。
109 |
五、人身攻击
110 |
请不要对任何个人或群体进行嘲讽、发布仇恨言论、挑拨他人矛盾。此类行为经查证后我们会对其进行警告,情节严重的将会永久封禁。
111 |
内容规范条例
112 |
一、标题党
113 |
为了保证Bilibili专栏的文章内容质量,我们拒绝各种以过度夸张、耸动的标题和内容去吸引人眼球的行为,标题党的标题种类包括但不限于:
114 |
(1) 使用过度夸张的惊叹词;
115 |
(2) 断章取义歪曲事实真相;
116 |
(3) 故意营造悬念引人好奇;
117 |
(4) 捏造正文中不存在的人、物、情节;
118 |
(5) 题文不符,标题存在歧义。
119 |
二、广告信息
120 |
为了保证用户的阅读体验,我们拒绝各类恶意营销式的广告!
121 |
以下的内容会被视为广告,我们会对其进行相应处理:
122 |
(1) 与投稿者个人以及文章内容无关的其他任何形式的推广;
123 |
(2) 其他商业产品、品牌、活动的推广。
124 |
三、文章内容侵权
125 |
投稿者须保证自己的文章为原创内容,若文章内容被查实为抄袭或滥用他人文章,我们会退回该稿件并对发布者予以处罚。
126 |
四、文章中其他不适宜收录的内容
127 |
被认定为不适宜收录的内容种类包括但不限于:
128 |
(1) 低创程度内容:文章不完整,主题不清晰,文章篇幅过短(200字以下);
129 |
(2) 图片与文章主题不相关或只是单纯的图集收录;
130 |
(3) 社会新闻以及关于社会新闻的评论文章,如新闻爆料、如打砸抢烧、交通事故、火灾等突发事故、官司纠纷等;
131 |
(4) 带有渲染社会负面现象,对于社会导向有误的文章。
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
153 |
154 |
--------------------------------------------------------------------------------
/src/renderer/css/fonts/icomoon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Generated by IcoMoon
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/renderer/utils/languages.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Regex : Transfer `{text: 'xxx', value: 'xxx'}`(Formatted) to ['xxx', 'xxx']
3 | * {\n 'text': ([^,]+),\n 'value': ([^\n]+)\n }
4 | * [$1, $2]
5 | */
6 |
7 | export const languages = new Map([
8 | ['APL', 'text/apl@apl@APL'],
9 | ['ASP.NET', 'application/x-aspx@asp@ASP.NET'],
10 | ['Asterisk', 'text/x-asterisk@r@Asterisk'],
11 | ['Brainfuck', 'text/x-brainfuck@brainfuck@Brainfuck'],
12 | ['C', 'text/x-csrc@clike@C'],
13 | ['C++', 'text/x-c++src@cpp@C++'],
14 | ['Cobol', 'text/x-cobol@c@Cobol'],
15 | ['C#', 'text/x-csharp@csharp@C#'],
16 | ['Clojure', 'text/x-clojure@clojure@Clojure'],
17 | ['ClojureScript', 'text/x-clojurescript@clojure@ClojureScript'],
18 | ['Closure Stylesheets (GSS)', 'text/x-gss@css@Closure Stylesheets (GSS)'],
19 | ['CMake', 'text/x-cmake@c@CMake'],
20 | ['CoffeeScript', 'coffeescript@coffeescript@CoffeeScript'],
21 | ['Cypher', 'application/x-cypher-query@r@Cypher'],
22 | ['Cython', 'text/x-cython@python@Cython'],
23 | ['Crystal', 'text/x-crystal@crystal@Crystal'],
24 | ['CSS', 'text/css@css@CSS'],
25 | ['CQL', 'text/x-cassandra@sql@CQL'],
26 | ['D', 'text/x-d@d@D'],
27 | ['Dart', 'dart@dart@Dart'],
28 | ['diff', 'text/x-diff@diff@diff'],
29 | ['Django', 'text/x-django@django@Django'],
30 | ['Dockerfile', 'text/x-dockerfile@dockerfile@Dockerfile'],
31 | ['DTD', 'application/xml-dtd@d@DTD'],
32 | ['Dylan', 'text/x-dylan@d@Dylan'],
33 | ['ECL', 'text/x-ecl@c@ECL'],
34 | ['edn', 'application/edn@clojure@edn'],
35 | ['Eiffel', 'text/x-eiffel@eiffel@Eiffel'],
36 | ['Elm', 'text/x-elm@elm@Elm'],
37 | ['Embedded Javascript', 'application/x-ejs@d@Embedded Javascript'],
38 | ['Embedded Ruby', 'application/x-erb@d@Embedded Ruby'],
39 | ['Erlang', 'text/x-erlang@erlang@Erlang'],
40 | ['Esper', 'text/x-esper@sql@Esper'],
41 | ['Factor', 'text/x-factor@r@Factor'],
42 | ['FCL', 'text/x-fcl@c@FCL'],
43 | ['Forth', 'text/x-forth@r@Forth'],
44 | ['Fortran', 'text/x-fortran@fortran@Fortran'],
45 | ['F#', 'text/x-fsharp@fsharp@F#'],
46 | ['Fsharp', 'text/x-fsharp@fsharp@F#'],
47 | ['Gherkin', 'text/x-feature@gherkin@Gherkin'],
48 | ['Go', 'text/x-go@go@Go'],
49 | ['Groovy', 'text/x-groovy@groovy@Groovy'],
50 | ['HAML', 'text/x-haml@haml@HAML'],
51 | ['Haskell', 'text/x-haskell@haskell@Haskell'],
52 | ['Haskell (Literate)', 'text/x-literate-haskell@r@Haskell (Literate)'],
53 | ['Haxe', 'text/x-haxe@haxe@Haxe'],
54 | ['HXML', 'text/x-hxml@haxe@HXML'],
55 | ['HTML', 'text/html@html@HTML'],
56 | ['HTTP', 'message/http@http@HTTP'],
57 | ['IDL', 'text/x-idl@d@IDL'],
58 | ['Pug', 'text/x-pug@pug@Pug'],
59 | ['Java', 'text/x-java@clike@Java'],
60 | ['JavaScript', 'javascript@javascript@JavaScript'],
61 | ['JSON', 'javascript@javascript@JSON'],
62 | ['JSON-LD', 'application/ld+json@javascript@JSON-LD'],
63 | ['JSX', 'text/jsx@jsx@JSX'],
64 | ['Jinja2', 'null@jinja2@Jinja2'],
65 | ['Julia', 'text/x-julia@julia@Julia'],
66 | ['Kotlin', 'text/x-kotlin@clike@Kotlin'],
67 | ['LESS', 'text/x-less@css@LESS'],
68 | ['LiveScript', 'text/x-livescript@livescript@LiveScript'],
69 | ['Lua', 'text/x-lua@lua@Lua'],
70 | ['Markdown', 'text/x-markdown@markdown@Markdown'],
71 | ['mIRC', 'text/mirc@r@mIRC'],
72 | ['MariaDB SQL', 'text/x-mariadb@sql@MariaDB SQL'],
73 | ['Mathematica', 'text/x-mathematica@c@Mathematica'],
74 | ['Modelica', 'text/x-modelica@d@Modelica'],
75 | ['MS SQL', 'text/x-mssql@sql@MS SQL'],
76 | ['MySQL', 'text/x-mysql@sql@MySQL'],
77 | ['Nginx', 'text/x-nginx-conf@nginx@Nginx'],
78 | ['NSIS', 'text/x-nsis@nsis@NSIS'],
79 | ['NTriples', 'ntriples@rip@NTriples'],
80 | ['ObjectiveC', 'text/x-objectivec@clike@Objective-C'],
81 | ['Octave', 'text/x-octave@c@Octave'],
82 | ['Oz', 'text/x-oz@oz@Oz'],
83 | ['Pascal', 'text/x-pascal@pascal@Pascal'],
84 | ['Perl', 'text/x-perl@perl@Perl'],
85 | ['PHP', 'php@php@PHP'],
86 | ['PLSQL', 'text/x-plsql@sql@PLSQL'],
87 | ['PowerShell', 'application/x-powershell@powershell@PowerShell'],
88 | ['Properties', 'text/x-properties@properties@Properties files'],
89 | ['Properties files', 'text/x-properties@properties@Properties files'],
90 | ['ProtoBuf', 'text/x-protobuf@protobuf@ProtoBuf'],
91 | ['Python', 'text/x-python@python@Python'],
92 | ['Puppet', 'text/x-puppet@puppet@Puppet'],
93 | ['R', 'text/x-rsrc@r@R'],
94 | ['RPM Changes', 'text/x-rpm-changes@r@RPM Changes'],
95 | ['RPM Spec', 'text/x-rpm-spec@r@RPM Spec'],
96 | ['Ruby', 'text/x-ruby@ruby@Ruby'],
97 | ['Rust', 'text/x-rustsrc@rust@Rust'],
98 | ['Sass', 'text/x-sass@sass@Sass'],
99 | ['Scala', 'text/x-scala@clike@Scala'],
100 | ['Scheme', 'text/x-scheme@scheme@Scheme'],
101 | ['SCSS', 'text/x-scss@css@SCSS'],
102 | ['Shell', 'shell@shell@Shell'],
103 | ['Smalltalk', 'text/x-stsrc@smalltalk@Smalltalk'],
104 | ['Smarty', 'text/x-smarty@smarty@Smarty'],
105 | ['Solr', 'text/x-solr@r@Solr'],
106 | ['SQL', 'text/x-sql@sql@SQL'],
107 | ['SQLite', 'text/x-sqlite@sql@SQLite'],
108 | ['Squirrel', 'text/x-squirrel@clike@Squirrel'],
109 | ['Stylus', 'text/x-styl@stylus@Stylus'],
110 | ['Swift', 'text/x-swift@swift@Swift'],
111 | ['SystemVerilog', 'text/x-systemverilog@verilog@SystemVerilog'],
112 | ['Tcl', 'text/x-tcl@tcl@Tcl'],
113 | ['Textile', 'text/x-textile@textile@Textile'],
114 | ['TiddlyWiki ', 'text/x-tiddlywiki@wiki@TiddlyWiki '],
115 | ['Tornado', 'text/x-tornado@r@Tornado'],
116 | ['troff', 'text/troff@r@troff'],
117 | ['TTCN', 'text/x-ttcn@c@TTCN'],
118 | ['TTCN_CFG', 'text/x-ttcn-cfg@c@TTCN_CFG'],
119 | ['Turtle', 'text/turtle@r@Turtle'],
120 | ['TypeScript', 'application/typescript@ts@TypeScript'],
121 | ['Tsx', 'text/typescript-jsx@tsx@TypeScript-JSX'],
122 | ['TypeScript-JSX', 'text/typescript-jsx@tsx@TypeScript-JSX'],
123 | ['Twig', 'text/x-twig@twig@Twig'],
124 | ['Web IDL', 'text/x-webidl@d@Web IDL'],
125 | ['VBScript', 'text/vbscript@rip@VBScript'],
126 | ['Velocity', 'text/velocity@c@Velocity'],
127 | ['Verilog', 'text/x-verilogverilog@verilog@Verilog'],
128 | ['VHDL', 'text/x-vhdl@vhdl@VHDL'],
129 | ['XML', 'xml@xml@XML'],
130 | ['XQuery', 'application/xquery@r@XQuery'],
131 | ['Yacas', 'text/x-yacas@c@Yacas'],
132 | ['YAML', 'yaml@yaml@YAML']
133 | ])
134 |
135 | export const languagesC = new Map([
136 | ['APL', 'text/apl@apl@APL'],
137 | ['ASP.NET', 'application/x-aspx@asp@ASP.NET'],
138 | ['ASTERISK', 'text/x-asterisk@r@Asterisk'],
139 | ['BRAINFUCK', 'text/x-brainfuck@brainfuck@Brainfuck'],
140 | ['C', 'text/x-csrc@clike@C'],
141 | ['C++', 'text/x-c++src@cpp@C++'],
142 | ['COBOL', 'text/x-cobol@c@Cobol'],
143 | ['C#', 'text/x-csharp@csharp@C#'],
144 | ['CLOJURE', 'text/x-clojure@clojure@Clojure'],
145 | ['CLOJURESCRIPT', 'text/x-clojurescript@clojure@ClojureScript'],
146 | ['CLOSURE STYLESHEETS (GSS)', 'text/x-gss@css@Closure Stylesheets (GSS)'],
147 | ['CMAKE', 'text/x-cmake@c@CMake'],
148 | ['COFFEESCRIPT', 'coffeescript@coffeescript@CoffeeScript'],
149 | ['CYPHER', 'application/x-cypher-query@r@Cypher'],
150 | ['CYTHON', 'text/x-cython@python@Cython'],
151 | ['CRYSTAL', 'text/x-crystal@crystal@Crystal'],
152 | ['CSS', 'text/css@css@CSS'],
153 | ['CQL', 'text/x-cassandra@sql@CQL'],
154 | ['D', 'text/x-d@d@D'],
155 | ['DART', 'dart@dart@Dart'],
156 | ['DIFF', 'text/x-diff@diff@diff'],
157 | ['DJANGO', 'text/x-django@django@Django'],
158 | ['DOCKERFILE', 'text/x-dockerfile@dockerfile@Dockerfile'],
159 | ['DTD', 'application/xml-dtd@d@DTD'],
160 | ['DYLAN', 'text/x-dylan@d@Dylan'],
161 | ['ECL', 'text/x-ecl@c@ECL'],
162 | ['EDN', 'application/edn@clojure@edn'],
163 | ['EIFFEL', 'text/x-eiffel@eiffel@Eiffel'],
164 | ['ELM', 'text/x-elm@elm@Elm'],
165 | ['EMBEDDED JAVASCRIPT', 'application/x-ejs@d@Embedded Javascript'],
166 | ['EMBEDDED RUBY', 'application/x-erb@d@Embedded Ruby'],
167 | ['ERLANG', 'text/x-erlang@erlang@Erlang'],
168 | ['ESPER', 'text/x-esper@sql@Esper'],
169 | ['FACTOR', 'text/x-factor@r@Factor'],
170 | ['FCL', 'text/x-fcl@c@FCL'],
171 | ['FORTH', 'text/x-forth@r@Forth'],
172 | ['FORTRAN', 'text/x-fortran@fortran@Fortran'],
173 | ['F#', 'text/x-fsharp@fsharp@F#'],
174 | ['FSHARP', 'text/x-fsharp@fsharp@F#'],
175 | ['GHERKIN', 'text/x-feature@gherkin@Gherkin'],
176 | ['GO', 'text/x-go@go@Go'],
177 | ['GROOVY', 'text/x-groovy@groovy@Groovy'],
178 | ['HAML', 'text/x-haml@haml@HAML'],
179 | ['HASKELL', 'text/x-haskell@haskell@Haskell'],
180 | ['HASKELL (LITERATE)', 'text/x-literate-haskell@r@Haskell (Literate)'],
181 | ['HAXE', 'text/x-haxe@haxe@Haxe'],
182 | ['HXML', 'text/x-hxml@haxe@HXML'],
183 | ['HTML', 'text/html@html@HTML'],
184 | ['HTTP', 'message/http@http@HTTP'],
185 | ['IDL', 'text/x-idl@d@IDL'],
186 | ['PUG', 'text/x-pug@pug@Pug'],
187 | ['JAVA', 'text/x-java@clike@Java'],
188 | ['JAVASCRIPT', 'javascript@javascript@JavaScript'],
189 | ['JSON', 'javascript@javascript@JSON'],
190 | ['JSON-LD', 'application/ld+json@javascript@JSON-LD'],
191 | ['JSX', 'text/jsx@jsx@JSX'],
192 | ['JINJA2', 'null@jinja2@Jinja2'],
193 | ['JULIA', 'text/x-julia@julia@Julia'],
194 | ['KOTLIN', 'text/x-kotlin@clike@Kotlin'],
195 | ['LESS', 'text/x-less@css@LESS'],
196 | ['LIVESCRIPT', 'text/x-livescript@livescript@LiveScript'],
197 | ['LUA', 'text/x-lua@lua@Lua'],
198 | ['MARKDOWN', 'text/x-markdown@markdown@Markdown'],
199 | ['MIRC', 'text/mirc@r@mIRC'],
200 | ['MARIADB SQL', 'text/x-mariadb@sql@MariaDB SQL'],
201 | ['MATHEMATICA', 'text/x-mathematica@c@Mathematica'],
202 | ['MODELICA', 'text/x-modelica@d@Modelica'],
203 | ['MS SQL', 'text/x-mssql@sql@MS SQL'],
204 | ['MYSQL', 'text/x-mysql@sql@MySQL'],
205 | ['NGINX', 'text/x-nginx-conf@nginx@Nginx'],
206 | ['NSIS', 'text/x-nsis@nsis@NSIS'],
207 | ['NTRIPLES', 'ntriples@rip@NTriples'],
208 | ['OBJECTIVEC', 'text/x-objectivec@clike@Objective-C'],
209 | ['OCTAVE', 'text/x-octave@c@Octave'],
210 | ['OZ', 'text/x-oz@oz@Oz'],
211 | ['PASCAL', 'text/x-pascal@pascal@Pascal'],
212 | ['PERL', 'text/x-perl@perl@Perl'],
213 | ['PHP', 'php@php@PHP'],
214 | ['PLSQL', 'text/x-plsql@sql@PLSQL'],
215 | ['POWERSHELL', 'application/x-powershell@powershell@PowerShell'],
216 | ['PROPERTIES', 'text/x-properties@properties@Properties files'],
217 | ['PROPERTIES FILES', 'text/x-properties@properties@Properties files'],
218 | ['PROTOBUF', 'text/x-protobuf@protobuf@ProtoBuf'],
219 | ['PYTHON', 'text/x-python@python@Python'],
220 | ['PUPPET', 'text/x-puppet@puppet@Puppet'],
221 | ['R', 'text/x-rsrc@r@R'],
222 | ['RPM CHANGES', 'text/x-rpm-changes@r@RPM Changes'],
223 | ['RPM SPEC', 'text/x-rpm-spec@r@RPM Spec'],
224 | ['RUBY', 'text/x-ruby@ruby@Ruby'],
225 | ['RUST', 'text/x-rustsrc@rust@Rust'],
226 | ['SASS', 'text/x-sass@sass@Sass'],
227 | ['SCALA', 'text/x-scala@clike@Scala'],
228 | ['SCHEME', 'text/x-scheme@scheme@Scheme'],
229 | ['SCSS', 'text/x-scss@css@SCSS'],
230 | ['SHELL', 'shell@shell@Shell'],
231 | ['SMALLTALK', 'text/x-stsrc@smalltalk@Smalltalk'],
232 | ['SMARTY', 'text/x-smarty@smarty@Smarty'],
233 | ['SOLR', 'text/x-solr@r@Solr'],
234 | ['SQL', 'text/x-sql@sql@SQL'],
235 | ['SQLITE', 'text/x-sqlite@sql@SQLite'],
236 | ['SQUIRREL', 'text/x-squirrel@clike@Squirrel'],
237 | ['STYLUS', 'text/x-styl@stylus@Stylus'],
238 | ['SWIFT', 'text/x-swift@swift@Swift'],
239 | ['SYSTEMVERILOG', 'text/x-systemverilog@verilog@SystemVerilog'],
240 | ['TCL', 'text/x-tcl@tcl@Tcl'],
241 | ['TEXTILE', 'text/x-textile@textile@Textile'],
242 | ['TIDDLYWIKI ', 'text/x-tiddlywiki@wiki@TiddlyWiki '],
243 | ['TORNADO', 'text/x-tornado@r@Tornado'],
244 | ['TROFF', 'text/troff@r@troff'],
245 | ['TTCN', 'text/x-ttcn@c@TTCN'],
246 | ['TTCN_CFG', 'text/x-ttcn-cfg@c@TTCN_CFG'],
247 | ['TURTLE', 'text/turtle@r@Turtle'],
248 | ['TYPESCRIPT', 'application/typescript@ts@TypeScript'],
249 | ['TSX', 'text/typescript-jsx@tsx@TypeScript-JSX'],
250 | ['TYPESCRIPT-JSX', 'text/typescript-jsx@tsx@TypeScript-JSX'],
251 | ['TWIG', 'text/x-twig@twig@Twig'],
252 | ['WEB IDL', 'text/x-webidl@d@Web IDL'],
253 | ['VBSCRIPT', 'text/vbscript@rip@VBScript'],
254 | ['VELOCITY', 'text/velocity@c@Velocity'],
255 | ['VERILOG', 'text/x-verilog@verilog@Verilog'],
256 | ['VHDL', 'text/x-vhdl@vhdl@VHDL'],
257 | ['XML', 'xml@xml@XML'],
258 | ['XQUERY', 'application/xquery@r@XQuery'],
259 | ['YACAS', 'text/x-yacas@c@Yacas'],
260 | ['YAML', 'yaml@yaml@YAML']
261 | ])
262 |
263 | export let unSupported = [
264 | 'ABAP',
265 | 'ACTIONSCRIPT',
266 | 'ADA',
267 | 'APACHECONF',
268 | 'APPLESCRIPT',
269 | 'ARDUINO',
270 | 'ARFF',
271 | 'ASCIIDOC',
272 | 'ASM6502',
273 | 'AUTOHOTKEY',
274 | 'AUTOIT',
275 | 'BASIC',
276 | 'BATCH',
277 | 'BISON',
278 | 'BRO',
279 | 'CLIKE',
280 | 'CSP',
281 | 'CSS-EXTRAS',
282 | 'ELIXIR',
283 | 'FLOW',
284 | 'GEDCOM',
285 | 'GIT',
286 | 'GLSL',
287 | 'graphql',
288 | 'HANDLEBARS',
289 | 'HPKP',
290 | 'HSTS',
291 | 'ICHIGOJAM',
292 | 'ICON',
293 | 'INFORM7',
294 | 'INI',
295 | 'IO',
296 | 'J',
297 | 'JOLIE',
298 | 'KEYMAN',
299 | 'LATEX',
300 | 'LIQUID',
301 | 'LISP',
302 | 'LOLCODE',
303 | 'MARKUP',
304 | 'MARKUP-TEMPLATING',
305 | 'MEL',
306 | 'MIZAR',
307 | 'MONKEY',
308 | 'N4JS',
309 | 'NASM',
310 | 'NIM',
311 | 'NIX',
312 | 'OCAML',
313 | 'OPENCL',
314 | 'PARIGP',
315 | 'PARSER',
316 | 'PHP-EXTRAS',
317 | 'PROCESSING',
318 | 'PROLOG',
319 | 'PURE',
320 | 'Q',
321 | 'QORE',
322 | 'RENPY',
323 | 'REASON',
324 | 'REST',
325 | 'RIP',
326 | 'ROBOCONF',
327 | 'SAS',
328 | 'SOY',
329 | 'TAP',
330 | 'TT2',
331 | 'VBNET',
332 | 'VIM',
333 | 'VISUAL-BASIC',
334 | 'WASM',
335 | 'WIKI',
336 | 'XEORA',
337 | 'XOJO'
338 | ]
339 |
340 | /**
341 | * It means that the former should be rendered,
342 | * but the latter can be displayed with prismjs.
343 | */
344 | export let translate = new Map([
345 | ['CMAKE', 'makefile'],
346 | ['DOCKERFILE', 'docker'],
347 | ['OCTAVE', 'matlab'],
348 | ['SHELL', 'bash'],
349 | ['JINJA2', 'django'],
350 | ['OCTAVE', 'matlab']
351 | ])
352 |
353 | /**
354 | * It means that the former can be displayed with prismjs,
355 | * but the latter should be rendered.
356 | */
357 | export let renderName = new Map([
358 | ['MATLAB', { ori: 'matlab', render: 'octave' }],
359 | ['JS', { ori: 'javascript', render: 'javascript' }],
360 | ['TS', { ori: 'typescript', render: 'typescript' }],
361 | ['PROP', { ori: 'properties', render: 'properties' }],
362 | ['MD', { ori: 'markdown', render: 'markdown' }],
363 | ['PY', { ori: 'python', render: 'python' }]
364 | ])
365 |
--------------------------------------------------------------------------------
/api.txt:
--------------------------------------------------------------------------------
1 | 查看分类(需要登录):
2 | https://member.bilibili.com/x/web/article/pre
3 |
4 | {"code":0,"data":{"categories":[{"id":2,"parent_id":0,"name":"动画","children":[{"id":4,"parent_id":2,"name":"动漫杂谈"},{"id":5,"parent_id":2,"name":"动漫资讯"},{"id":31,"parent_id":2,"name":"动画技术"}]},{"id":1,"parent_id":0,"name":"游戏","children":[{"id":6,"parent_id":1,"name":"单机游戏"},{"id":7,"parent_id":1,"name":"电子竞技"},{"id":8,"parent_id":1,"name":"手机游戏"},{"id":9,"parent_id":1,"name":"网络游戏"},{"id":10,"parent_id":1,"name":"桌游棋牌"}]},{"id":28,"parent_id":0,"name":"影视","children":[{"id":12,"parent_id":28,"name":"电影"},{"id":35,"parent_id":28,"name":"电视剧"},{"id":36,"parent_id":28,"name":"纪录片"},{"id":37,"parent_id":28,"name":"综艺"}]},{"id":3,"parent_id":0,"name":"生活","children":[{"id":13,"parent_id":3,"name":"美食"},{"id":21,"parent_id":3,"name":"萌宠"},{"id":14,"parent_id":3,"name":"时尚"},{"id":22,"parent_id":3,"name":"运动"},{"id":15,"parent_id":3,"name":"日常"}]},{"id":29,"parent_id":0,"name":"兴趣","children":[{"id":23,"parent_id":29,"name":"绘画"},{"id":24,"parent_id":29,"name":"手工"},{"id":38,"parent_id":29,"name":"摄影"},{"id":39,"parent_id":29,"name":"音乐舞蹈"},{"id":11,"parent_id":29,"name":"模型手办"}]},{"id":16,"parent_id":0,"name":"轻小说","children":[{"id":18,"parent_id":16,"name":"原创连载"},{"id":19,"parent_id":16,"name":"同人连载"},{"id":32,"parent_id":16,"name":"短篇小说"},{"id":20,"parent_id":16,"name":"小说杂谈"}]},{"id":17,"parent_id":0,"name":"科技","children":[{"id":25,"parent_id":17,"name":"人文历史"},{"id":33,"parent_id":17,"name":"自然"},{"id":26,"parent_id":17,"name":"数码"},{"id":27,"parent_id":17,"name":"汽车"},{"id":34,"parent_id":17,"name":"学习"}]}],"myinfo":{"mid":5756570,"uname":"某昨P","face":"http://i1.hdslb.com/bfs/face/7115c5ff964c5aea3bc70792fdb2073b1f6dcb19.jpg","banned":false,"level":5,"activated":true,"deftime":1527928480,"deftime_end":1529210080,"deftime_msg":"发布时间离当前时间必须大于4小时且小于15天,请重新选择。","commercial":0,"identify_check":{"code":0,"msg":"已实名认证"}},"toplimit":5},"message":"0","ttl":1}
5 |
6 |
7 |
8 | 查看活动(不需要登录):
9 | https://www.bilibili.com/activity/list/article
10 |
11 | {"code":0,"data":[{"id":10558,"oid":0,"type":12,"state":1,"stime":"2018-05-22 00:00:00","etime":"2018-07-23 00:00:00","ctime":"2018-05-10 20:01:31","mtime":"2018-05-22 00:44:28","name":"\u300a\u5e72\u676f\uff01\u4e16\u754c\u676f\u300b\u5e94\u63f4\u5f81\u96c6","author":"xufan","act_url":"https:\/\/www.bilibili.com\/blackboard\/activity-cheersworldcup2018.html","cover":"","letime":"2018-05-26 00:00:00","lstime":"2018-05-22 00:00:00","dic":"","flag":"38","uetime":"0000-00-00 00:00:00","ustime":"2018-05-22 00:00:00","level":"0","h5_cover":"","tags":"\u5e72\u676f\uff01\u4e16\u754c\u676f"}]}
12 |
13 |
14 | 查看专栏信息(需要登录):
15 | http://api.bilibili.com/x/article/creative/draft/view?aid=6159
16 |
17 | {"code":0,"message":"0","ttl":1,"data":{"id":6159,"title":"2","content":"","summary":"","banner_url":"","reason":"","template_id":4,"state":0,"reprint":0,"image_urls":[],"origin_image_urls":[],"tags":[],"category":{"id":0,"parent_id":0,"name":""},"author":{"mid":5756570,"name":"","face":"","pendant":{"pid":0,"name":"","image":"","expire":0},"official_verify":{"type":0,"desc":""},"nameplate":{"nid":0,"name":"","image":"","image_small":"","level":"","condition":""}},"stats":null,"publish_time":0,"ctime":0,"mtime":1527914451,"view_url":"","edit_url":"","is_preview":0,"dynamic_intro":"","list":null}}
18 |
19 |
20 | 查看所有专栏(需要登录):
21 | https://api.bilibili.com/x/article/creative/article/list?group=【①】&sort=【②】&pn=
22 | ① Group
23 | 0: 全部文章
24 | 1: 审核中
25 | 2: 已通过
26 | 3: 未通过
27 | ② Sort
28 | 1: 按创建时间排序
29 | 2: 按喜欢数排序
30 | 3: 按评论数排序
31 | 4: ---
32 | 5: 按收藏数排序
33 | 6: 按投币数排序
34 |
35 | {"artlist":{"articles":[{"id":139179,"title":"【某昨】对Minecraft Mod本地化现状的评价及未来的展望","content":"","summary":"大家好,这里是咕咕咕准备高考的某昨。这期专栏,我们来聊一聊Minecraft Mod本地化的现状和对未来的展望。个人意见,欢迎dalao点评。从Minecraft Mod出现以来,本地化可以说经过了三","banner_url":"https://i0.hdslb.com/bfs/article/63b99aaf7bfb4332e521da161d1b28f7c2e6549a.png","reason":"","template_id":4,"state":0,"reprint":1,"image_urls":["https://i0.hdslb.com/bfs/article/63b99aaf7bfb4332e521da161d1b28f7c2e6549a.png"],"origin_image_urls":["https://i0.hdslb.com/bfs/article/63b99aaf7bfb4332e521da161d1b28f7c2e6549a.png"],"tags":[],"category":{"id":1,"parent_id":0,"name":"游戏"},"author":{"mid":5756570,"name":"","face":"","pendant":{"pid":0,"name":"","image":"","expire":0},"official_verify":{"type":0,"desc":""},"nameplate":{"nid":0,"name":"","image":"","image_small":"","level":"","condition":""}},"stats":{"view":189,"favorite":4,"like":5,"dislike":0,"reply":3,"share":0,"coin":4},"publish_time":1515002136,"ctime":1515001381,"mtime":0,"view_url":"https://www.bilibili.com/read/cv139179","edit_url":"https://member.bilibili.com/article-text/mobile?aid=139179\u0026type=2","is_preview":0,"dynamic_intro":"","list":null},{"id":131983,"title":"[某昨]2017年度歌单总结(个人向)(1/4)","content":"","summary":"大家好,这里是专栏鸽了好久的某昨。伴随着圣诞节的钟声(其实不存在的啦),我们很快就要迎来2018年的到来了。在此即将辞旧迎新之际,就让我们伴随着《ジングルベルがとまらない》的歌声,来看看这一年对我而言","banner_url":"https://i0.hdslb.com/bfs/article/0431e6b2b200fdcf74e772fae759f7fe182fa429.jpg","reason":"","template_id":4,"state":0,"reprint":1,"image_urls":["https://i0.hdslb.com/bfs/article/69b18ef78676e5726ded1b4519a6bd0c7ad05ef1.jpg"],"origin_image_urls":["https://i0.hdslb.com/bfs/article/7e9ed2f8802522ac7b63eb0c7d2f59e615c0b32c.jpg"],"tags":[],"category":{"id":3,"parent_id":0,"name":"生活"},"author":{"mid":5756570,"name":"","face":"","pendant":{"pid":0,"name":"","image":"","expire":0},"official_verify":{"type":0,"desc":""},"nameplate":{"nid":0,"name":"","image":"","image_small":"","level":"","condition":""}},"stats":{"view":480,"favorite":2,"like":3,"dislike":0,"reply":1,"share":1,"coin":0},"publish_time":1514640268,"ctime":1514640090,"mtime":0,"view_url":"https://www.bilibili.com/read/cv131983","edit_url":"https://member.bilibili.com/article-text/mobile?aid=131983\u0026type=2","is_preview":0,"dynamic_intro":"","list":null},{"id":35521,"title":"[Mod Idea]Ep.00 奇怪的脑洞\u0026Minecraft与我","content":"","summary":"大家好,我是某昨,这里又开了个新坑。坑如其名,Mod Idea,就是关于Mod的一些想法。从我接触Minecraft Mod以来,就开始有很多想法涌现。有些成为了大坑(如我Github上的InterC","banner_url":"https://i0.hdslb.com/bfs/article/9d0312d1c577c0c61a30b0375a39fc28ff1eec3f.jpg","reason":"","template_id":4,"state":0,"reprint":1,"image_urls":["https://i0.hdslb.com/bfs/article/1b83019bcf6e25ab0d5417fad21aaa6cef79ac68.jpg"],"origin_image_urls":["https://i0.hdslb.com/bfs/article/9d0312d1c577c0c61a30b0375a39fc28ff1eec3f.jpg"],"tags":[],"category":{"id":1,"parent_id":0,"name":"游戏"},"author":{"mid":5756570,"name":"","face":"","pendant":{"pid":0,"name":"","image":"","expire":0},"official_verify":{"type":0,"desc":""},"nameplate":{"nid":0,"name":"","image":"","image_small":"","level":"","condition":""}},"stats":{"view":721,"favorite":12,"like":8,"dislike":0,"reply":3,"share":0,"coin":2},"publish_time":1508056504,"ctime":1508056170,"mtime":0,"view_url":"https://www.bilibili.com/read/cv35521","edit_url":"https://member.bilibili.com/article-text/mobile?aid=35521\u0026type=2","is_preview":0,"dynamic_intro":"","list":null},{"id":34259,"title":"ForestryMC-1.10 Mod兼容指南① 总序,实用拓展(Actually Additions)","content":"","summary":"之前玩Age of Engineering需要大量用到Actually Additions的油菜。众所周知,AoE的配方被魔改得非常致命(不知道的快去看direwolf20受虐,2333),而林业的农","banner_url":"https://i0.hdslb.com/bfs/article/c30707abd0a82a4c8246e1911a84fdf0b6249121.jpg","reason":"","template_id":4,"state":0,"reprint":1,"image_urls":["https://i0.hdslb.com/bfs/article/bde18a88dcc532f608ae271e92a5c2442c357f16.png"],"origin_image_urls":["https://i0.hdslb.com/bfs/article/0f7027d75dab4ba8651c7edcc15d24110afed3f6.png"],"tags":[],"category":{"id":1,"parent_id":0,"name":"游戏"},"author":{"mid":5756570,"name":"","face":"","pendant":{"pid":0,"name":"","image":"","expire":0},"official_verify":{"type":0,"desc":""},"nameplate":{"nid":0,"name":"","image":"","image_small":"","level":"","condition":""}},"stats":{"view":880,"favorite":20,"like":20,"dislike":0,"reply":5,"share":0,"coin":2},"publish_time":1507960791,"ctime":1507958686,"mtime":0,"view_url":"https://www.bilibili.com/read/cv34259","edit_url":"https://member.bilibili.com/article-text/mobile?aid=34259\u0026type=2","is_preview":0,"dynamic_intro":"","list":null},{"id":26467,"title":"Tranquility 12周目完结撒鱼(花?)(❁´◡`❁)*✲゚*","content":"","summary":"今天好不容易填完MooncakeCraft的小坑,还没来得及感叹1.12看不透,就发现十二周目完结了。正好中间阿仇有段内容没有录上,我就来讲讲我直播时的所见所感吧。[OP!老夫的OP呢!手机不能内嵌视","banner_url":"https://i0.hdslb.com/bfs/article/7a3f775523df76cd1ec121356712ce9d8b3c04ec.png","reason":"","template_id":4,"state":0,"reprint":1,"image_urls":["https://i0.hdslb.com/bfs/article/7a3f775523df76cd1ec121356712ce9d8b3c04ec.png"],"origin_image_urls":["https://i0.hdslb.com/bfs/article/7a3f775523df76cd1ec121356712ce9d8b3c04ec.png"],"tags":[],"category":{"id":1,"parent_id":0,"name":"游戏"},"author":{"mid":5756570,"name":"","face":"","pendant":{"pid":0,"name":"","image":"","expire":0},"official_verify":{"type":0,"desc":""},"nameplate":{"nid":0,"name":"","image":"","image_small":"","level":"","condition":""}},"stats":{"view":167,"favorite":2,"like":6,"dislike":0,"reply":5,"share":0,"coin":1},"publish_time":1507134325,"ctime":1507134054,"mtime":0,"view_url":"https://www.bilibili.com/read/cv26467","edit_url":"https://member.bilibili.com/article-text/mobile?aid=26467\u0026type=2","is_preview":0,"dynamic_intro":"","list":null},{"id":1073,"title":"[FFmpeg探秘]Ep.(2) 从node-fluent-ffmpeg开始","content":"","summary":"这一节,我们从node-fluent-ffmpeg入手,对FFmpeg的流媒体机制进行探秘。node-fluent-ffmpeg是基于Nodejs下基于FFmpeg的流媒体API,提供了操控FFmpe","banner_url":"https://i0.hdslb.com/bfs/article/89e994bd4d8d67565431d1669442c0373bdfe2f6.jpg","reason":"","template_id":4,"state":0,"reprint":1,"image_urls":["https://i0.hdslb.com/bfs/article/5ade60de04b6220fea9b0b0786e72a5196212964.jpg"],"origin_image_urls":["https://i0.hdslb.com/bfs/article/89e994bd4d8d67565431d1669442c0373bdfe2f6.jpg"],"tags":[],"category":{"id":17,"parent_id":0,"name":"科技"},"author":{"mid":5756570,"name":"","face":"","pendant":{"pid":0,"name":"","image":"","expire":0},"official_verify":{"type":0,"desc":""},"nameplate":{"nid":0,"name":"","image":"","image_small":"","level":"","condition":""}},"stats":{"view":461,"favorite":5,"like":4,"dislike":0,"reply":4,"share":0,"coin":0},"publish_time":1501947959,"ctime":1501945698,"mtime":0,"view_url":"https://www.bilibili.com/read/cv1073","edit_url":"https://member.bilibili.com/article-text/mobile?aid=1073\u0026type=2","is_preview":0,"dynamic_intro":"","list":null},{"id":859,"title":"[FFmpeg探秘]Ep.(1) 什么是FFmpeg?","content":"","summary":"FFmpeg是什么?相信很多人都或多或少听说过它的大名,尤其是对于Up主们来说,总会或多或少地瞄到小丸工具箱tools目录下的ffmpeg.exe,或者在压制的日志中看到ffmpeg的影子。大部分人相","banner_url":"https://i0.hdslb.com/bfs/article/b44ad4602b302708adc14480bb3ea840d74360c3.jpg","reason":"","template_id":4,"state":0,"reprint":1,"image_urls":["https://i0.hdslb.com/bfs/article/570509ab7f602b2579f50f33d6669813c1439773.jpg"],"origin_image_urls":["https://i0.hdslb.com/bfs/article/b44ad4602b302708adc14480bb3ea840d74360c3.jpg"],"tags":[],"category":{"id":17,"parent_id":0,"name":"科技"},"author":{"mid":5756570,"name":"","face":"","pendant":{"pid":0,"name":"","image":"","expire":0},"official_verify":{"type":0,"desc":""},"nameplate":{"nid":0,"name":"","image":"","image_small":"","level":"","condition":""}},"stats":{"view":178,"favorite":8,"like":5,"dislike":0,"reply":3,"share":1,"coin":0},"publish_time":1501839500,"ctime":1501838554,"mtime":0,"view_url":"https://www.bilibili.com/read/cv859","edit_url":"https://member.bilibili.com/article-text/mobile?aid=859\u0026type=2","is_preview":0,"dynamic_intro":"","list":null}],"type":{"all":7,"audit":0,"passed":7,"not_passed":0},"page":{"pn":1,"ps":20,"total":7}},"code":0,"message":"0"}
36 |
37 |
38 | 查看专栏统计数据(需要登录):
39 | https://member.bilibili.com/x/web/data/article
40 |
41 | {"code":0,"data":{"view":3096,"reply":27,"like":51,"coin":9,"fav":53,"incr_view":1,"incr_reply":0,"incr_like":0,"incr_coin":0,"incr_fav":0},"message":"0","ttl":1}
42 |
43 |
44 | 查看专栏评论(需要登录):
45 | https://member.bilibili.com/x/web/replies?order=【①】&filter=【②】&is_hidden=【③】&type=【④】&oid=【⑤】&pn=【⑥】&ps=【⑦】
46 | ① Order
47 | ctime: 时间排序
48 | like: 点赞数排序
49 | count: 回复数排序
50 | ② Filter
51 | 无: 全部时间
52 | 0: 最近一天
53 | 1: 最近七天
54 | 3: 最近一年
55 | ③ Is_hidden
56 | ④ Type
57 | ⑤ Oid
58 | 专栏的编号,空默认返回所有专栏的评论
59 | ⑥ Pn
60 | 返回第n页的评论
61 | ⑦ Ps
62 | 每一页的评论数量,最多为50
63 |
64 | {"code":0,"data":[{"message":"回复 @某昨P:还行","id":667982354,"floor":2,"count":0,"root":667972068,"oid":264640,"ctime":"2018-03-03 21:19:09","mtime":"2018-03-03 21:19:09","state":0,"parent":667974566,"mid":11511536,"like":0,"replier":"水天宫_宠儿","uface":"http://i2.hdslb.com/bfs/face/3450ae7870e27335f5e88fb8276080c84c6a4112.jpg","cover":"","title":"","relation":2,"is_elec":0,"type":12,"root_info":{"rpid":667974566,"oid":264640,"type":12,"mid":5756570,"root":667972068,"parent":667972068,"count":0,"rcount":0,"floor":1,"state":0,"attr":0,"ctime":1520082920,"like":0,"action":0,"member":{"mid":"5756570","uname":"某昨P","sex":"男","sign":"高三咸鱼冲一把,二十天过后说不定就在上科大了(肝)。有条件可以来Twitter支持我~: @Yesterday17CN","avatar":"http://i1.hdslb.com/bfs/face/7115c5ff964c5aea3bc70792fdb2073b1f6dcb19.jpg","rank":"10000","DisplayRank":"0","level_info":{"current_level":5,"current_min":0,"current_exp":0,"next_exp":0},"pendant":{"pid":153,"name":"citrus","image":"http://i2.hdslb.com/bfs/face/f2d3a85b611eb2ef13cb64415187e3e9fd487ec8.png","expire":1556208000},"nameplate":{"nid":67,"name":"正义之士","image":"http://i1.hdslb.com/bfs/face/5ad735b804886637348de1c95484360acf2a9987.png","image_small":"http://i1.hdslb.com/bfs/face/ef1397ba9d6eb7bab1f230ee7516086432f349de.png","level":"普通勋章","condition":"累计众裁数 \u003e= 200"},"official_verify":{"type":-1,"desc":""},"vip":{"vipType":2,"vipDueDate":1561564800000,"dueRemark":"","accessStatus":0,"vipStatus":1,"vipStatusWarn":""}},"content":{"message":"emm 这个是随手发的 之前发的测试反而还没过审","ipi":717494505,"plat":1,"device":"","members":null},"replies":null},"parent_info":{"rpid":667974566,"oid":264640,"type":12,"mid":5756570,"root":667972068,"parent":667972068,"count":0,"rcount":0,"floor":1,"state":0,"attr":0,"ctime":1520082920,"like":0,"action":0,"member":{"mid":"5756570","uname":"某昨P","sex":"男","sign":"高三咸鱼冲一把,二十天过后说不定就在上科大了(肝)。有条件可以来Twitter支持我~: @Yesterday17CN","avatar":"http://i1.hdslb.com/bfs/face/7115c5ff964c5aea3bc70792fdb2073b1f6dcb19.jpg","rank":"10000","DisplayRank":"0","level_info":{"current_level":5,"current_min":0,"current_exp":0,"next_exp":0},"pendant":{"pid":153,"name":"citrus","image":"http://i2.hdslb.com/bfs/face/f2d3a85b611eb2ef13cb64415187e3e9fd487ec8.png","expire":1556208000},"nameplate":{"nid":67,"name":"正义之士","image":"http://i1.hdslb.com/bfs/face/5ad735b804886637348de1c95484360acf2a9987.png","image_small":"http://i1.hdslb.com/bfs/face/ef1397ba9d6eb7bab1f230ee7516086432f349de.png","level":"普通勋章","condition":"累计众裁数 \u003e= 200"},"official_verify":{"type":-1,"desc":""},"vip":{"vipType":2,"vipDueDate":1561564800000,"dueRemark":"","accessStatus":0,"vipStatus":1,"vipStatusWarn":""}},"content":{"message":"emm 这个是随手发的 之前发的测试反而还没过审","ipi":717494505,"plat":1,"device":"","members":null},"replies":null}},{"message":"emm 这个是随手发的 之前发的测试反而还没过审","id":667974566,"floor":1,"count":0,"root":667972068,"oid":264640,"ctime":"2018-03-03 21:15:20","mtime":"2018-03-03 21:15:20","state":0,"parent":667972068,"mid":5756570,"like":0,"replier":"某昨P","uface":"http://i1.hdslb.com/bfs/face/7115c5ff964c5aea3bc70792fdb2073b1f6dcb19.jpg","cover":"","title":"","relation":1,"is_elec":1,"type":12,"root_info":{"rpid":667972068,"oid":264640,"type":12,"mid":11511536,"root":0,"parent":0,"count":2,"rcount":2,"floor":1,"state":0,"attr":0,"ctime":1520082844,"like":0,"action":0,"member":{"mid":"11511536","uname":"水天宫_宠儿","sex":"保密","sign":"普通的跑跑玩家","avatar":"http://i2.hdslb.com/bfs/face/3450ae7870e27335f5e88fb8276080c84c6a4112.jpg","rank":"10000","DisplayRank":"0","level_info":{"current_level":5,"current_min":0,"current_exp":0,"next_exp":0},"pendant":{"pid":105,"name":"纳米核心","image":"http://i2.hdslb.com/bfs/face/b67a37542d33d093ff28780848448e0a1c78932a.png","expire":1558022400},"nameplate":{"nid":4,"name":"青铜殿堂","image":"http://i2.hdslb.com/bfs/face/2879cd5fb8518f7c6da75887994c1b2a7fe670bd.png","image_small":"http://i1.hdslb.com/bfs/face/6707c120e00a3445933308fd9b7bd9fad99e9ec4.png","level":"普通勋章","condition":"单个自制视频总播放数\u003e=1万"},"official_verify":{"type":-1,"desc":""},"vip":{"vipType":2,"vipDueDate":1558022400000,"dueRemark":"","accessStatus":0,"vipStatus":1,"vipStatusWarn":""}},"content":{"message":"封面车万惊了","ipi":1885418070,"plat":2,"device":"","members":null},"replies":null},"parent_info":{"rpid":667972068,"oid":264640,"type":12,"mid":11511536,"root":0,"parent":0,"count":2,"rcount":2,"floor":1,"state":0,"attr":0,"ctime":1520082844,"like":0,"action":0,"member":{"mid":"11511536","uname":"水天宫_宠儿","sex":"保密","sign":"普通的跑跑玩家","avatar":"http://i2.hdslb.com/bfs/face/3450ae7870e27335f5e88fb8276080c84c6a4112.jpg","rank":"10000","DisplayRank":"0","level_info":{"current_level":5,"current_min":0,"current_exp":0,"next_exp":0},"pendant":{"pid":105,"name":"纳米核心","image":"http://i2.hdslb.com/bfs/face/b67a37542d33d093ff28780848448e0a1c78932a.png","expire":1558022400},"nameplate":{"nid":4,"name":"青铜殿堂","image":"http://i2.hdslb.com/bfs/face/2879cd5fb8518f7c6da75887994c1b2a7fe670bd.png","image_small":"http://i1.hdslb.com/bfs/face/6707c120e00a3445933308fd9b7bd9fad99e9ec4.png","level":"普通勋章","condition":"单个自制视频总播放数\u003e=1万"},"official_verify":{"type":-1,"desc":""},"vip":{"vipType":2,"vipDueDate":1558022400000,"dueRemark":"","accessStatus":0,"vipStatus":1,"vipStatusWarn":""}},"content":{"message":"封面车万惊了","ipi":1885418070,"plat":2,"device":"","members":null},"replies":null}},{"message":"封面车万惊了","id":667972068,"floor":1,"count":2,"root":0,"oid":264640,"ctime":"2018-03-03 21:14:04","mtime":"2018-03-03 21:19:09","state":0,"parent":0,"mid":11511536,"like":0,"replier":"水天宫_宠儿","uface":"http://i2.hdslb.com/bfs/face/3450ae7870e27335f5e88fb8276080c84c6a4112.jpg","cover":"","title":"","relation":2,"is_elec":0,"type":12,"root_info":null,"parent_info":null},{"message":"长达5个月的2-3天( ´_ゝ`)","id":573150095,"floor":4,"count":0,"root":0,"oid":1073,"ctime":"2018-01-06 16:09:37","mtime":"2018-01-06 16:09:37","state":0,"parent":0,"mid":172844097,"like":0,"replier":"ZeroAurora233","uface":"http://i0.hdslb.com/bfs/face/64d304b8f0c34e81f8ed1d1ea4d48e8b8e70e3e6.jpg","cover":"https://i0.hdslb.com/bfs/article/5ade60de04b6220fea9b0b0786e72a5196212964.jpg","title":"[FFmpeg探秘]Ep.(2) 从node-fluent-ffmpeg开始","relation":2,"is_elec":0,"type":12,"root_info":null,"parent_info":null},{"message":"Σ(゚д゚;)","id":570414165,"floor":3,"count":0,"root":0,"oid":139179,"ctime":"2018-01-04 12:28:04","mtime":"2018-01-04 12:28:04","state":0,"parent":0,"mid":17288555,"like":0,"replier":"数象位至","uface":"http://i1.hdslb.com/bfs/face/a2eb4e5a09a5ec66dae0193f31604666b75a1ffd.jpg","cover":"https://i0.hdslb.com/bfs/article/63b99aaf7bfb4332e521da161d1b28f7c2e6549a.png","title":"【某昨】对Minecraft Mod本地化现状的评价及未来的展望","relation":2,"is_elec":0,"type":12,"root_info":null,"parent_info":null},{"message":"原来你也是高三啊(重点错","id":570230286,"floor":2,"count":0,"root":0,"oid":139179,"ctime":"2018-01-04 07:13:01","mtime":"2018-01-04 07:13:01","state":0,"parent":0,"mid":6411282,"like":0,"replier":"ShuPiR","uface":"http://i2.hdslb.com/bfs/face/b248a3c9aef2910323fd9307deb4ec018c8e10f5.jpg","cover":"https://i0.hdslb.com/bfs/article/63b99aaf7bfb4332e521da161d1b28f7c2e6549a.png","title":"【某昨】对Minecraft Mod本地化现状的评价及未来的展望","relation":2,"is_elec":0,"type":12,"root_info":null,"parent_info":null},{"message":"懵着逼看完[小电视_困惑]","id":570164041,"floor":1,"count":0,"root":0,"oid":139179,"ctime":"2018-01-04 02:08:49","mtime":"2018-01-04 02:08:49","state":0,"parent":0,"mid":11885971,"like":0,"replier":"gloomy丶banana","uface":"http://i1.hdslb.com/bfs/face/fd4cfd01dd729549c45f9df222f23d35da7f6605.jpg","cover":"https://i0.hdslb.com/bfs/article/63b99aaf7bfb4332e521da161d1b28f7c2e6549a.png","title":"【某昨】对Minecraft Mod本地化现状的评价及未来的展望","relation":2,"is_elec":0,"type":12,"root_info":null,"parent_info":null},{"message":"真·五分钟审核[小电视_赞]","id":564112354,"floor":1,"count":0,"root":0,"oid":131983,"ctime":"2017-12-30 21:29:02","mtime":"2017-12-30 21:29:02","state":0,"parent":0,"mid":5756570,"like":0,"replier":"某昨P","uface":"http://i1.hdslb.com/bfs/face/7115c5ff964c5aea3bc70792fdb2073b1f6dcb19.jpg","cover":"https://i0.hdslb.com/bfs/article/69b18ef78676e5726ded1b4519a6bd0c7ad05ef1.jpg","title":"[某昨]2017年度歌单总结(个人向)(1/4)","relation":1,"is_elec":1,"type":12,"root_info":null,"parent_info":null},{"message":"之后一P呢 ( ´_ゝ`)","id":482663442,"floor":3,"count":0,"root":0,"oid":1073,"ctime":"2017-11-17 13:43:12","mtime":"2017-11-17 13:43:12","state":0,"parent":0,"mid":1926839,"like":0,"replier":"米柚子","uface":"http://i1.hdslb.com/bfs/face/722a413092f7448b1be23113c2ba2e105216999d.jpg","cover":"https://i0.hdslb.com/bfs/article/5ade60de04b6220fea9b0b0786e72a5196212964.jpg","title":"[FFmpeg探秘]Ep.(2) 从node-fluent-ffmpeg开始","relation":2,"is_elec":0,"type":12,"root_info":null,"parent_info":null},{"message":"啥时候更新啊[小电视_发愁]","id":453005422,"floor":2,"count":0,"root":0,"oid":1073,"ctime":"2017-10-18 22:45:45","mtime":"2017-10-18 22:45:45","state":0,"parent":0,"mid":4134388,"like":0,"replier":"若隐若现的节操","uface":"http://i1.hdslb.com/bfs/face/2f2db3962655f57faea4a71ace6e6f1fe28410e3.jpg","cover":"https://i0.hdslb.com/bfs/article/5ade60de04b6220fea9b0b0786e72a5196212964.jpg","title":"[FFmpeg探秘]Ep.(2) 从node-fluent-ffmpeg开始","relation":2,"is_elec":0,"type":12,"root_info":null,"parent_info":null},{"message":"或许这就是大佬吧","id":450318270,"floor":3,"count":0,"root":0,"oid":35521,"ctime":"2017-10-16 11:55:32","mtime":"2017-10-28 12:44:36","state":0,"parent":0,"mid":17288555,"like":1,"replier":"数象位至","uface":"http://i1.hdslb.com/bfs/face/a2eb4e5a09a5ec66dae0193f31604666b75a1ffd.jpg","cover":"https://i0.hdslb.com/bfs/article/1b83019bcf6e25ab0d5417fad21aaa6cef79ac68.jpg","title":"[Mod Idea]Ep.00 奇怪的脑洞\u0026Minecraft与我","relation":2,"is_elec":0,"type":12,"root_info":null,"parent_info":null},{"message":"看了第一段顺着链接去看direwolf20了,过了好几天才突然想起来这文根本就没有看。。","id":450265353,"floor":5,"count":0,"root":0,"oid":34259,"ctime":"2017-10-16 10:29:35","mtime":"2017-10-16 10:29:35","state":0,"parent":0,"mid":8119687,"like":0,"replier":"苏凌10","uface":"http://i1.hdslb.com/bfs/face/48ce0a27d8d3e120e6bcbfde60a03ea737202e3c.jpg","cover":"https://i0.hdslb.com/bfs/article/bde18a88dcc532f608ae271e92a5c2442c357f16.png","title":"ForestryMC-1.10 Mod兼容指南① 总序,实用拓展(Actually Additions)","relation":1,"is_elec":0,"type":12,"root_info":null,"parent_info":null},{"message":"催更mf2(๑•ั็ω•็ั๑)","id":449527854,"floor":2,"count":0,"root":0,"oid":35521,"ctime":"2017-10-15 16:56:18","mtime":"2017-10-15 16:56:18","state":0,"parent":0,"mid":8786969,"like":0,"replier":"Ten_CI","uface":"http://i1.hdslb.com/bfs/face/8754451bd07e2b4fd5ff0952bdb4fe3b724a2a89.jpg","cover":"https://i0.hdslb.com/bfs/article/1b83019bcf6e25ab0d5417fad21aaa6cef79ac68.jpg","title":"[Mod Idea]Ep.00 奇怪的脑洞\u0026Minecraft与我","relation":2,"is_elec":0,"type":12,"root_info":null,"parent_info":null},{"message":"少年很有想法[小电视_赞]","id":449509377,"floor":1,"count":0,"root":0,"oid":35521,"ctime":"2017-10-15 16:39:05","mtime":"2017-10-15 16:39:05","state":0,"parent":0,"mid":11885971,"like":0,"replier":"gloomy丶banana","uface":"http://i1.hdslb.com/bfs/face/fd4cfd01dd729549c45f9df222f23d35da7f6605.jpg","cover":"https://i0.hdslb.com/bfs/article/1b83019bcf6e25ab0d5417fad21aaa6cef79ac68.jpg","title":"[Mod Idea]Ep.00 奇怪的脑洞\u0026Minecraft与我","relation":2,"is_elec":0,"type":12,"root_info":null,"parent_info":null},{"message":"教程?滋磁!","id":448452033,"floor":4,"count":0,"root":0,"oid":34259,"ctime":"2017-10-14 20:31:03","mtime":"2017-11-02 15:40:58","state":0,"parent":0,"mid":7939974,"like":0,"replier":"Sf·Chipen","uface":"http://i1.hdslb.com/bfs/face/c60a099e42c2c327983b3b1c228d96fab5dfad01.jpg","cover":"https://i0.hdslb.com/bfs/article/bde18a88dcc532f608ae271e92a5c2442c357f16.png","title":"ForestryMC-1.10 Mod兼容指南① 总序,实用拓展(Actually Additions)","relation":2,"is_elec":0,"type":12,"root_info":null,"parent_info":null},{"message":"支持支持 猿佬","id":448063172,"floor":3,"count":0,"root":0,"oid":34259,"ctime":"2017-10-14 14:33:56","mtime":"2017-10-14 20:08:41","state":6,"parent":0,"mid":27612973,"like":0,"replier":"陌于千鹤","uface":"http://i1.hdslb.com/bfs/face/fb1f49d6404e0fe63bb598cc2322feb227f5360d.jpg","cover":"https://i0.hdslb.com/bfs/article/bde18a88dcc532f608ae271e92a5c2442c357f16.png","title":"ForestryMC-1.10 Mod兼容指南① 总序,实用拓展(Actually Additions)","relation":1,"is_elec":0,"type":12,"root_info":null,"parent_info":null},{"message":"菜籽油出原油,炼金术[小电视_吃惊]","id":448055405,"floor":2,"count":0,"root":0,"oid":34259,"ctime":"2017-10-14 14:24:59","mtime":"2017-10-14 15:23:25","state":0,"parent":0,"mid":8786969,"like":1,"replier":"Ten_CI","uface":"http://i1.hdslb.com/bfs/face/8754451bd07e2b4fd5ff0952bdb4fe3b724a2a89.jpg","cover":"https://i0.hdslb.com/bfs/article/bde18a88dcc532f608ae271e92a5c2442c357f16.png","title":"ForestryMC-1.10 Mod兼容指南① 总序,实用拓展(Actually Additions)","relation":2,"is_elec":0,"type":12,"root_info":null,"parent_info":null},{"message":"943来的(=・ω・=)","id":448050392,"floor":1,"count":0,"root":0,"oid":34259,"ctime":"2017-10-14 14:19:06","mtime":"2017-10-15 00:05:15","state":0,"parent":0,"mid":172844097,"like":1,"replier":"ZeroAurora233","uface":"http://i0.hdslb.com/bfs/face/64d304b8f0c34e81f8ed1d1ea4d48e8b8e70e3e6.jpg","cover":"https://i0.hdslb.com/bfs/article/bde18a88dcc532f608ae271e92a5c2442c357f16.png","title":"ForestryMC-1.10 Mod兼容指南① 总序,实用拓展(Actually Additions)","relation":2,"is_elec":0,"type":12,"root_info":null,"parent_info":null},{"message":"文笔很不错哦","id":437765528,"floor":3,"count":0,"root":0,"oid":26467,"ctime":"2017-10-05 22:30:17","mtime":"2017-10-05 22:30:17","state":0,"parent":0,"mid":4435845,"like":0,"replier":"酒石酸菌","uface":"http://i2.hdslb.com/bfs/face/2e9af19b0fd8d4b58f6a1bbd3302add09f820340.jpg","cover":"https://i0.hdslb.com/bfs/article/7a3f775523df76cd1ec121356712ce9d8b3c04ec.png","title":"Tranquility 12周目完结撒鱼(花?)(❁´◡`❁)*✲゚*","relation":1,"is_elec":0,"type":12,"root_info":null,"parent_info":null},{"message":"看完了,非常棒","id":437765121,"floor":1,"count":0,"root":0,"oid":1073,"ctime":"2017-10-05 22:30:02","mtime":"2017-10-28 13:01:22","state":0,"parent":0,"mid":4435845,"like":1,"replier":"酒石酸菌","uface":"http://i2.hdslb.com/bfs/face/2e9af19b0fd8d4b58f6a1bbd3302add09f820340.jpg","cover":"https://i0.hdslb.com/bfs/article/5ade60de04b6220fea9b0b0786e72a5196212964.jpg","title":"[FFmpeg探秘]Ep.(2) 从node-fluent-ffmpeg开始","relation":1,"is_elec":0,"type":12,"root_info":null,"parent_info":null},{"message":"虎摸咸鱼","id":436790976,"floor":1,"count":0,"root":436783616,"oid":26467,"ctime":"2017-10-05 10:40:50","mtime":"2017-10-05 10:40:50","state":0,"parent":436783616,"mid":626658,"like":0,"replier":"煎饼XX","uface":"http://i0.hdslb.com/bfs/face/b8bc2e8279a9468a4d07fc2996dbfc2d63477aeb.jpg","cover":"https://i0.hdslb.com/bfs/article/7a3f775523df76cd1ec121356712ce9d8b3c04ec.png","title":"Tranquility 12周目完结撒鱼(花?)(❁´◡`❁)*✲゚*","relation":1,"is_elec":0,"type":12,"root_info":{"rpid":436783616,"oid":26467,"type":12,"mid":17288555,"root":0,"parent":0,"count":1,"rcount":1,"floor":2,"state":0,"attr":0,"ctime":1507170881,"like":0,"action":0,"member":{"mid":"17288555","uname":"数象位至","sex":"保密","sign":"众人皆佬我独咸!(/TДT)/","avatar":"http://i2.hdslb.com/bfs/face/a2eb4e5a09a5ec66dae0193f31604666b75a1ffd.jpg","rank":"10000","DisplayRank":"0","level_info":{"current_level":4,"current_min":0,"current_exp":0,"next_exp":0},"pendant":{"pid":0,"name":"","image":"","expire":0},"nameplate":{"nid":7,"name":"见习搬运工","image":"http://i1.hdslb.com/bfs/face/8478fb7c54026cd47f09daa493a1b1683113a90d.png","image_small":"http://i2.hdslb.com/bfs/face/50eef47c3a30a75659d3cc298cfb09031d1a2ce5.png","level":"普通勋章","condition":"转载视频投稿通过总数\u003e=10"},"official_verify":{"type":-1,"desc":""},"vip":{"vipType":0,"vipDueDate":0,"dueRemark":"","accessStatus":0,"vipStatus":0,"vipStatusWarn":""}},"content":{"message":"_(:з」∠)_","ipi":2871447432,"plat":1,"device":"","members":null},"replies":null},"parent_info":{"rpid":436783616,"oid":26467,"type":12,"mid":17288555,"root":0,"parent":0,"count":1,"rcount":1,"floor":2,"state":0,"attr":0,"ctime":1507170881,"like":0,"action":0,"member":{"mid":"17288555","uname":"数象位至","sex":"保密","sign":"众人皆佬我独咸!(/TДT)/","avatar":"http://i2.hdslb.com/bfs/face/a2eb4e5a09a5ec66dae0193f31604666b75a1ffd.jpg","rank":"10000","DisplayRank":"0","level_info":{"current_level":4,"current_min":0,"current_exp":0,"next_exp":0},"pendant":{"pid":0,"name":"","image":"","expire":0},"nameplate":{"nid":7,"name":"见习搬运工","image":"http://i1.hdslb.com/bfs/face/8478fb7c54026cd47f09daa493a1b1683113a90d.png","image_small":"http://i2.hdslb.com/bfs/face/50eef47c3a30a75659d3cc298cfb09031d1a2ce5.png","level":"普通勋章","condition":"转载视频投稿通过总数\u003e=10"},"official_verify":{"type":-1,"desc":""},"vip":{"vipType":0,"vipDueDate":0,"dueRemark":"","accessStatus":0,"vipStatus":0,"vipStatusWarn":""}},"content":{"message":"_(:з」∠)_","ipi":2871447432,"plat":1,"device":"","members":null},"replies":null}},{"message":"_(:з」∠)_","id":436783616,"floor":2,"count":1,"root":0,"oid":26467,"ctime":"2017-10-05 10:34:41","mtime":"2017-10-05 10:40:50","state":0,"parent":0,"mid":17288555,"like":0,"replier":"数象位至","uface":"http://i1.hdslb.com/bfs/face/a2eb4e5a09a5ec66dae0193f31604666b75a1ffd.jpg","cover":"https://i0.hdslb.com/bfs/article/7a3f775523df76cd1ec121356712ce9d8b3c04ec.png","title":"Tranquility 12周目完结撒鱼(花?)(❁´◡`❁)*✲゚*","relation":2,"is_elec":0,"type":12,"root_info":null,"parent_info":null},{"message":"9氏游览:服务器里一群肝帝\n仇式游览:走过炸过千万不要错过(雾","id":436458802,"floor":1,"count":0,"root":436450883,"oid":26467,"ctime":"2017-10-05 00:39:12","mtime":"2017-10-05 00:39:12","state":0,"parent":436450883,"mid":5756570,"like":0,"replier":"某昨P","uface":"http://i1.hdslb.com/bfs/face/7115c5ff964c5aea3bc70792fdb2073b1f6dcb19.jpg","cover":"https://i0.hdslb.com/bfs/article/7a3f775523df76cd1ec121356712ce9d8b3c04ec.png","title":"Tranquility 12周目完结撒鱼(花?)(❁´◡`❁)*✲゚*","relation":1,"is_elec":1,"type":12,"root_info":{"rpid":436450883,"oid":26467,"type":12,"mid":8786969,"root":0,"parent":0,"count":1,"rcount":1,"floor":1,"state":0,"attr":0,"ctime":1507134743,"like":0,"action":0,"member":{"mid":"8786969","uname":"Ten_CI","sex":"男","sign":"信仰圣光吧(物理)","avatar":"http://i1.hdslb.com/bfs/face/8754451bd07e2b4fd5ff0952bdb4fe3b724a2a89.jpg","rank":"10000","DisplayRank":"0","level_info":{"current_level":5,"current_min":0,"current_exp":0,"next_exp":0},"pendant":{"pid":0,"name":"","image":"","expire":0},"nameplate":{"nid":57,"name":"收集萌新","image":"http://i2.hdslb.com/bfs/face/7767275600ea63d351b22fa87ec15a79aa24e5e5.png","image_small":"http://i0.hdslb.com/bfs/face/6589d992655595bf51543f268040eaeaed372fae.png","level":"普通勋章","condition":"同时拥有粉丝勋章\u003e=5个"},"official_verify":{"type":-1,"desc":""},"vip":{"vipType":2,"vipDueDate":1563379200000,"dueRemark":"","accessStatus":0,"vipStatus":1,"vipStatusWarn":""}},"content":{"message":"完解炸龙堆(°∀°)ノ","ipi":3657770900,"plat":2,"device":"","members":null},"replies":null},"parent_info":{"rpid":436450883,"oid":26467,"type":12,"mid":8786969,"root":0,"parent":0,"count":1,"rcount":1,"floor":1,"state":0,"attr":0,"ctime":1507134743,"like":0,"action":0,"member":{"mid":"8786969","uname":"Ten_CI","sex":"男","sign":"信仰圣光吧(物理)","avatar":"http://i1.hdslb.com/bfs/face/8754451bd07e2b4fd5ff0952bdb4fe3b724a2a89.jpg","rank":"10000","DisplayRank":"0","level_info":{"current_level":5,"current_min":0,"current_exp":0,"next_exp":0},"pendant":{"pid":0,"name":"","image":"","expire":0},"nameplate":{"nid":57,"name":"收集萌新","image":"http://i2.hdslb.com/bfs/face/7767275600ea63d351b22fa87ec15a79aa24e5e5.png","image_small":"http://i0.hdslb.com/bfs/face/6589d992655595bf51543f268040eaeaed372fae.png","level":"普通勋章","condition":"同时拥有粉丝勋章\u003e=5个"},"official_verify":{"type":-1,"desc":""},"vip":{"vipType":2,"vipDueDate":1563379200000,"dueRemark":"","accessStatus":0,"vipStatus":1,"vipStatusWarn":""}},"content":{"message":"完解炸龙堆(°∀°)ノ","ipi":3657770900,"plat":2,"device":"","members":null},"replies":null}},{"message":"完解炸龙堆(°∀°)ノ","id":436450883,"floor":1,"count":1,"root":0,"oid":26467,"ctime":"2017-10-05 00:32:23","mtime":"2017-10-05 00:39:12","state":0,"parent":0,"mid":8786969,"like":0,"replier":"Ten_CI","uface":"http://i1.hdslb.com/bfs/face/8754451bd07e2b4fd5ff0952bdb4fe3b724a2a89.jpg","cover":"https://i0.hdslb.com/bfs/article/7a3f775523df76cd1ec121356712ce9d8b3c04ec.png","title":"Tranquility 12周目完结撒鱼(花?)(❁´◡`❁)*✲゚*","relation":2,"is_elec":0,"type":12,"root_info":null,"parent_info":null},{"message":"格式转换的内容相对来说是比较简单的,最主要的是控制编码和码率之类的,第二篇有一种简单的压制成flv的方法。一般转的时候限定h.26-4就可以了\n我之后有空多写写吧(","id":371523323,"floor":1,"count":0,"root":368866022,"oid":859,"ctime":"2017-08-11 11:06:10","mtime":"2017-08-11 11:06:10","state":0,"parent":368866022,"mid":5756570,"like":0,"replier":"某昨P","uface":"http://i1.hdslb.com/bfs/face/7115c5ff964c5aea3bc70792fdb2073b1f6dcb19.jpg","cover":"https://i0.hdslb.com/bfs/article/570509ab7f602b2579f50f33d6669813c1439773.jpg","title":"[FFmpeg探秘]Ep.(1) 什么是FFmpeg?","relation":1,"is_elec":1,"type":12,"root_info":{"rpid":368866022,"oid":859,"type":12,"mid":4028313,"root":0,"parent":0,"count":1,"rcount":1,"floor":2,"state":0,"attr":0,"ctime":1502250126,"like":0,"action":0,"member":{"mid":"4028313","uname":"dyzdyz010","sex":"男","sign":"Vocaloid调教新人入坑","avatar":"http://i1.hdslb.com/bfs/face/4f88ab09757d2387d6a924151c41ec2cb7b0d020.jpg","rank":"10000","DisplayRank":"0","level_info":{"current_level":5,"current_min":0,"current_exp":0,"next_exp":0},"pendant":{"pid":0,"name":"","image":"","expire":0},"nameplate":{"nid":0,"name":"","image":"","image_small":"","level":"","condition":""},"official_verify":{"type":-1,"desc":""},"vip":{"vipType":1,"vipDueDate":1531843200000,"dueRemark":"","accessStatus":0,"vipStatus":1,"vipStatusWarn":""}},"content":{"message":"补充,我个人更关注ffmpeg的格式转换功能,包括视频和音频,大部分格式之间都可以相互转换,甚至可以直接从视频中提取出音频输出为文件","ipi":2025962028,"plat":2,"device":"","members":null},"replies":null},"parent_info":{"rpid":368866022,"oid":859,"type":12,"mid":4028313,"root":0,"parent":0,"count":1,"rcount":1,"floor":2,"state":0,"attr":0,"ctime":1502250126,"like":0,"action":0,"member":{"mid":"4028313","uname":"dyzdyz010","sex":"男","sign":"Vocaloid调教新人入坑","avatar":"http://i1.hdslb.com/bfs/face/4f88ab09757d2387d6a924151c41ec2cb7b0d020.jpg","rank":"10000","DisplayRank":"0","level_info":{"current_level":5,"current_min":0,"current_exp":0,"next_exp":0},"pendant":{"pid":0,"name":"","image":"","expire":0},"nameplate":{"nid":0,"name":"","image":"","image_small":"","level":"","condition":""},"official_verify":{"type":-1,"desc":""},"vip":{"vipType":1,"vipDueDate":1531843200000,"dueRemark":"","accessStatus":0,"vipStatus":1,"vipStatusWarn":""}},"content":{"message":"补充,我个人更关注ffmpeg的格式转换功能,包括视频和音频,大部分格式之间都可以相互转换,甚至可以直接从视频中提取出音频输出为文件","ipi":2025962028,"plat":2,"device":"","members":null},"replies":null}},{"message":"前来支持,真么快就出了","id":370947245,"floor":3,"count":0,"root":0,"oid":859,"ctime":"2017-08-10 21:54:12","mtime":"2017-11-17 13:42:19","state":0,"parent":0,"mid":7861137,"like":1,"replier":"STeven8888","uface":"http://i2.hdslb.com/bfs/face/f6b53b876c34d09decbe399ef32a14e008d86108.jpg","cover":"https://i0.hdslb.com/bfs/article/570509ab7f602b2579f50f33d6669813c1439773.jpg","title":"[FFmpeg探秘]Ep.(1) 什么是FFmpeg?","relation":2,"is_elec":0,"type":12,"root_info":null,"parent_info":null},{"message":"补充,我个人更关注ffmpeg的格式转换功能,包括视频和音频,大部分格式之间都可以相互转换,甚至可以直接从视频中提取出音频输出为文件","id":368866022,"floor":2,"count":1,"root":0,"oid":859,"ctime":"2017-08-09 11:42:06","mtime":"2017-08-11 11:06:10","state":0,"parent":0,"mid":4028313,"like":0,"replier":"dyzdyz010","uface":"http://i1.hdslb.com/bfs/face/4f88ab09757d2387d6a924151c41ec2cb7b0d020.jpg","cover":"https://i0.hdslb.com/bfs/article/570509ab7f602b2579f50f33d6669813c1439773.jpg","title":"[FFmpeg探秘]Ep.(1) 什么是FFmpeg?","relation":2,"is_elec":0,"type":12,"root_info":null,"parent_info":null},{"message":"期待后文~","id":362810336,"floor":1,"count":0,"root":0,"oid":859,"ctime":"2017-08-04 20:36:12","mtime":"2017-08-05 23:08:26","state":0,"parent":0,"mid":5760446,"like":2,"replier":"花儿不哭","uface":"http://i1.hdslb.com/bfs/face/f4c52f7f52b8d5aaad70b1afd2fb064b673b5466.jpg","cover":"https://i0.hdslb.com/bfs/article/570509ab7f602b2579f50f33d6669813c1439773.jpg","title":"[FFmpeg探秘]Ep.(1) 什么是FFmpeg?","relation":1,"is_elec":0,"type":12,"root_info":null,"parent_info":null}],"message":"0","pager":{"current":1,"size":50,"total":28},"ttl":1}
65 |
--------------------------------------------------------------------------------