Compare commits
No commits in common. "master" and "multi-arch" have entirely different histories.
master
...
multi-arch
16 changed files with 682 additions and 690 deletions
43
.github/workflows/clippy-fmt.yml
vendored
Normal file
43
.github/workflows/clippy-fmt.yml
vendored
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
name: Lint
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, reopened]
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
fmt:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install Rust
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
components: rustfmt
|
||||||
|
- name: Check with rustfmt
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: fmt
|
||||||
|
args: --all -- --check
|
||||||
|
|
||||||
|
clippy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install Rust
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
components: clippy
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- name: Check with Clippy
|
||||||
|
uses: actions-rs/clippy-check@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
args: --workspace --tests --all-features
|
49
.github/workflows/coverage.yml
vendored
Normal file
49
.github/workflows/coverage.yml
vendored
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
name: Coverage
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, reopened]
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_and_test:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
version:
|
||||||
|
- nightly
|
||||||
|
|
||||||
|
name: ${{ matrix.version }} - x86_64-unknown-linux-gnu
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: ⚡ Cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/registry
|
||||||
|
~/.cargo/git
|
||||||
|
target
|
||||||
|
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
|
||||||
|
- name: Install ${{ matrix.version }}
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: ${{ matrix.version }}-x86_64-unknown-linux-gnu
|
||||||
|
profile: minimal
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- name: Generate coverage file
|
||||||
|
if: (github.ref == 'refs/heads/master' || github.event_name == 'pull_request')
|
||||||
|
uses: actions-rs/tarpaulin@v0.1
|
||||||
|
with:
|
||||||
|
args: "-t 1200"
|
||||||
|
env:
|
||||||
|
GIT_HASH: 8e77345f1597e40c2e266cb4e6dee74888918a61
|
||||||
|
|
||||||
|
- name: Upload to Codecov
|
||||||
|
uses: codecov/codecov-action@v2
|
||||||
|
if: github.ref == 'refs/heads/master'
|
70
.github/workflows/linux.yml
vendored
Normal file
70
.github/workflows/linux.yml
vendored
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
name: Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, reopened]
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_and_test:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
version:
|
||||||
|
#- 1.51.0
|
||||||
|
- stable
|
||||||
|
# - nightly
|
||||||
|
|
||||||
|
name: ${{ matrix.version }} - x86_64-unknown-linux-gnu
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: ⚡ Cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
/var/lib/docker
|
||||||
|
~/.cargo/registry
|
||||||
|
~/.cargo/git
|
||||||
|
target
|
||||||
|
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
|
||||||
|
- name: Login to DockerHub
|
||||||
|
if: (github.ref == 'refs/heads/master' || github.event_name == 'push') && github.repository == 'realaravinth/libmedium'
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Install ${{ matrix.version }}
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: ${{ matrix.version }}-x86_64-unknown-linux-gnu
|
||||||
|
profile: minimal
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- name: build
|
||||||
|
run: make
|
||||||
|
|
||||||
|
- name: run tests
|
||||||
|
run: make test
|
||||||
|
|
||||||
|
- name: build and publish docker images
|
||||||
|
run: make docker-publish
|
||||||
|
|
||||||
|
- name: generate documentation
|
||||||
|
if: matrix.version == 'stable' && (github.repository == 'realaravinth/libmedium')
|
||||||
|
run: make doc
|
||||||
|
env:
|
||||||
|
GIT_HASH: 8e77345f1597e40c2e266cb4e6dee74888918a61 # dummy value
|
||||||
|
|
||||||
|
- name: Deploy to GitHub libmedium
|
||||||
|
if: matrix.version == 'stable' && (github.repository == 'realaravinth/libmedium')
|
||||||
|
uses: JamesIves/github-pages-deploy-action@3.7.1
|
||||||
|
with:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
BRANCH: gh-libmedium
|
||||||
|
FOLDER: target/doc
|
|
@ -1,8 +1,6 @@
|
||||||
steps:
|
steps:
|
||||||
backend:
|
backend:
|
||||||
image: rust
|
image: rust
|
||||||
when:
|
|
||||||
event: [push, pull_request, tag, deployment, cron, manual, release]
|
|
||||||
environment:
|
environment:
|
||||||
- GIT_HASH=8e77345f1597e40c2e266cb4e6dee74888918a61 # dummy value
|
- GIT_HASH=8e77345f1597e40c2e266cb4e6dee74888918a61 # dummy value
|
||||||
- COMPILED_DATE=2021-07-21
|
- COMPILED_DATE=2021-07-21
|
||||||
|
@ -18,10 +16,13 @@ steps:
|
||||||
image: woodpeckerci/plugin-docker-buildx
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
when:
|
when:
|
||||||
event: [pull_request]
|
event: [pull_request]
|
||||||
|
secrets: [docker_token]
|
||||||
settings:
|
settings:
|
||||||
dry_run: true
|
dry_run: true
|
||||||
repo: realaravinth/libmedium
|
repo: realaravinth/libmedium
|
||||||
username: realaravinth
|
username: realaravinth
|
||||||
|
password:
|
||||||
|
from_secret: DOCKER_TOKEN
|
||||||
platforms: linux/amd64,linux/arm64/v8
|
platforms: linux/amd64,linux/arm64/v8
|
||||||
tag: latest
|
tag: latest
|
||||||
|
|
||||||
|
@ -31,7 +32,9 @@ steps:
|
||||||
when:
|
when:
|
||||||
event: [push, tag, deployment]
|
event: [push, tag, deployment]
|
||||||
branch: master
|
branch: master
|
||||||
|
secrets: [docker_token]
|
||||||
settings:
|
settings:
|
||||||
|
dry_run: true
|
||||||
repo: realaravinth/libmedium
|
repo: realaravinth/libmedium
|
||||||
username: realaravinth
|
username: realaravinth
|
||||||
password:
|
password:
|
||||||
|
|
1064
Cargo.lock
generated
1064
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -16,7 +16,7 @@ actix-rt = "2"
|
||||||
actix-web = "4.0.1"
|
actix-web = "4.0.1"
|
||||||
bincode = "1.3.3"
|
bincode = "1.3.3"
|
||||||
chrono = "0.4.23"
|
chrono = "0.4.23"
|
||||||
config = "0.14"
|
config = "0.13"
|
||||||
derive_more = "0.99"
|
derive_more = "0.99"
|
||||||
futures = "0.3.17"
|
futures = "0.3.17"
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
|
@ -30,11 +30,10 @@ sled = "0.34.7"
|
||||||
syntect = "5.0.0"
|
syntect = "5.0.0"
|
||||||
url = "2.2"
|
url = "2.2"
|
||||||
actix-web-codegen-const-routes = "0.2.0"
|
actix-web-codegen-const-routes = "0.2.0"
|
||||||
sha256 = "1.5.0"
|
|
||||||
|
|
||||||
[dependencies.graphql_client]
|
[dependencies.graphql_client]
|
||||||
features = ["reqwest"]
|
features = ["reqwest"]
|
||||||
version = "0.14.0"
|
version = "0.13.0"
|
||||||
|
|
||||||
[dependencies.reqwest]
|
[dependencies.reqwest]
|
||||||
features = ["json"]
|
features = ["json"]
|
||||||
|
|
|
@ -57,8 +57,8 @@ business.
|
||||||
| http://md.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion/ | N/A | Hetzner | [~vern](https://vern.cc) |
|
| http://md.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion/ | N/A | Hetzner | [~vern](https://vern.cc) |
|
||||||
| http://vernaqj2qr2pijpgvf3od6ssc3ulz3nv52gwr3hba5l6humuzmgq.b32.i2p/ | N/A | Hetzner | [~vern](https://vern.cc) |
|
| http://vernaqj2qr2pijpgvf3od6ssc3ulz3nv52gwr3hba5l6humuzmgq.b32.i2p/ | N/A | Hetzner | [~vern](https://vern.cc) |
|
||||||
| https://medium.hostux.net | France | Gandi | [hostux](https://hostux.net) |
|
| https://medium.hostux.net | France | Gandi | [hostux](https://hostux.net) |
|
||||||
| https://r.sudovanilla.org | US | Selfhosted | [SudoVanilla](https://sudovanilla.org) |
|
| https://read.sudovanilla.com | US | Cloudflare | [SudoVanilla](https://sudovanilla.com) |
|
||||||
| https://libmedium.ducks.party | DE | Datalix | [ducks.party](https://ducks.party) |
|
|
||||||
## Deploy
|
## Deploy
|
||||||
|
|
||||||
1. Grab [`./config/default.toml`](./config/default.toml) and make
|
1. Grab [`./config/default.toml`](./config/default.toml) and make
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
debug = true
|
debug = true
|
||||||
source_code = "https://git.batsense.net/realaravinth/libmedium"
|
source_code = "https://github.com/realaravinth/libmedium"
|
||||||
#cache = "/var/lib/libmedium"
|
#cache = "/var/lib/libmedium"
|
||||||
|
|
||||||
[server]
|
[server]
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
|
||||||
"extends": ["config:recommended", ":dependencyDashboard"],
|
|
||||||
"labels": ["renovate-bot"],
|
|
||||||
"prHourlyLimit": 0,
|
|
||||||
"timezone": "Asia/kolkata",
|
|
||||||
"prCreation": "immediate",
|
|
||||||
"vulnerabilityAlerts": {
|
|
||||||
"enabled": true,
|
|
||||||
"labels": ["renovate-bot", "renovate-security", "security"]
|
|
||||||
}
|
|
||||||
}
|
|
27
src/data.rs
27
src/data.rs
|
@ -21,7 +21,6 @@ use graphql_client::{reqwest::post_graphql, GraphQLQuery};
|
||||||
use reqwest::header::USER_AGENT;
|
use reqwest::header::USER_AGENT;
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sha256::digest;
|
|
||||||
use sled::{Db, Tree};
|
use sled::{Db, Tree};
|
||||||
|
|
||||||
use crate::proxy::StringUtils;
|
use crate::proxy::StringUtils;
|
||||||
|
@ -164,14 +163,14 @@ impl Data {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_post_light(&self, id: &str) -> Option<PostUrl> {
|
pub async fn get_post_light(&self, id: &str) -> PostUrl {
|
||||||
match self.posts.get(id) {
|
match self.posts.get(id) {
|
||||||
Ok(Some(v)) => {
|
Ok(Some(v)) => {
|
||||||
let cached: PostResp = bincode::deserialize(&v[..]).unwrap();
|
let cached: PostResp = bincode::deserialize(&v[..]).unwrap();
|
||||||
Some(PostUrl {
|
PostUrl {
|
||||||
slug: cached.unique_slug,
|
slug: cached.unique_slug,
|
||||||
username: cached.creator.username,
|
username: cached.creator.username,
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let vars = get_post_light::Variables { id: id.to_owned() };
|
let vars = get_post_light::Variables { id: id.to_owned() };
|
||||||
|
@ -180,16 +179,10 @@ impl Data {
|
||||||
let res = post_graphql::<GetPostLight, _>(&self.client, URL, vars)
|
let res = post_graphql::<GetPostLight, _>(&self.client, URL, vars)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
if res.data.is_none() {
|
let res = res.data.expect("missing response data").post.unwrap();
|
||||||
None
|
PostUrl {
|
||||||
} else {
|
slug: res.unique_slug,
|
||||||
match res.data.expect("missing response data").post {
|
username: res.creator.username,
|
||||||
None => None,
|
|
||||||
Some(res) => Some(PostUrl {
|
|
||||||
slug: res.unique_slug,
|
|
||||||
username: res.creator.username,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,21 +287,19 @@ impl Data {
|
||||||
filepath: &file.file_name,
|
filepath: &file.file_name,
|
||||||
code: &file.content,
|
code: &file.content,
|
||||||
};
|
};
|
||||||
file.content = highlight.syntax_highlight(&digest(&file.raw_url));
|
file.content = highlight.syntax_highlight();
|
||||||
files.push(file);
|
files.push(file);
|
||||||
GistContent {
|
GistContent {
|
||||||
files,
|
files,
|
||||||
html_url: gist_url,
|
html_url: gist_url,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let mut index = 1;
|
|
||||||
gist.files.iter_mut().for_each(|f| {
|
gist.files.iter_mut().for_each(|f| {
|
||||||
let highlight = render_html::SourcegraphQuery {
|
let highlight = render_html::SourcegraphQuery {
|
||||||
filepath: &f.file_name,
|
filepath: &f.file_name,
|
||||||
code: &f.content,
|
code: &f.content,
|
||||||
};
|
};
|
||||||
f.content = highlight.syntax_highlight(&digest(&f.raw_url));
|
f.content = highlight.syntax_highlight();
|
||||||
index += 1;
|
|
||||||
});
|
});
|
||||||
gist
|
gist
|
||||||
};
|
};
|
||||||
|
|
34
src/post.rs
34
src/post.rs
|
@ -345,7 +345,6 @@ pub fn apply_markup(
|
||||||
) -> Vec<String> {
|
) -> Vec<String> {
|
||||||
let mut paragraphs: Vec<String> = Vec::with_capacity(data.content.body_model.paragraphs.len());
|
let mut paragraphs: Vec<String> = Vec::with_capacity(data.content.body_model.paragraphs.len());
|
||||||
let mut state = ListState::default();
|
let mut state = ListState::default();
|
||||||
let mut no_render_html = false;
|
|
||||||
for (pindex, p) in data.content.body_model.paragraphs.iter().enumerate() {
|
for (pindex, p) in data.content.body_model.paragraphs.iter().enumerate() {
|
||||||
let mut pos = PositionMap::default();
|
let mut pos = PositionMap::default();
|
||||||
if p.type_ == "H3" && pindex == 0 {
|
if p.type_ == "H3" && pindex == 0 {
|
||||||
|
@ -384,42 +383,33 @@ pub fn apply_markup(
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut content = String::with_capacity(p.text.len());
|
let mut content = String::with_capacity(p.text.len());
|
||||||
let start = &Markup::start(p, gists, pindex, &mut state);
|
content += &Markup::start(p, gists, pindex, &mut state);
|
||||||
content += start;
|
|
||||||
if start == "<pre>" {
|
|
||||||
no_render_html = true;
|
|
||||||
}
|
|
||||||
pos.arr.sort();
|
pos.arr.sort();
|
||||||
let mut page = String::default();
|
|
||||||
if let Some(first) = pos.arr.first() {
|
if let Some(first) = pos.arr.first() {
|
||||||
page += p.text.slice(cur..*first as usize);
|
//content += p.text.substring(cur, *first as usize);
|
||||||
|
content += p.text.slice(cur..*first as usize);
|
||||||
cur = incr_cur(cur, *first);
|
cur = incr_cur(cur, *first);
|
||||||
for point in pos.arr.iter() {
|
for point in pos.arr.iter() {
|
||||||
|
//content.push(p.text.substring(start, start + point);
|
||||||
|
// if *point != 0 {
|
||||||
|
|
||||||
if cur != *point as usize {
|
if cur != *point as usize {
|
||||||
page += p.text.slice(cur..*point as usize);
|
// content += p.text.substring(cur, *point as usize);
|
||||||
|
content += p.text.slice(cur..*point as usize);
|
||||||
}
|
}
|
||||||
// }
|
// }
|
||||||
let pos_markups = pos.map.get(point).unwrap();
|
let pos_markups = pos.map.get(point).unwrap();
|
||||||
for m in pos_markups.iter() {
|
for m in pos_markups.iter() {
|
||||||
page += &m.apply_markup(pindex);
|
content += &m.apply_markup(pindex);
|
||||||
}
|
}
|
||||||
cur = incr_cur(cur, *point);
|
cur = incr_cur(cur, *point);
|
||||||
}
|
}
|
||||||
log::debug!("LAST");
|
log::debug!("LAST");
|
||||||
page += p.text.slice(cur..);
|
content += p.text.slice(cur..);
|
||||||
let end = &Markup::end(p, pindex, &mut state);
|
content += &Markup::end(p, pindex, &mut state);
|
||||||
if end == "</pre>" {
|
|
||||||
no_render_html = false;
|
|
||||||
}
|
|
||||||
content += &page;
|
|
||||||
content += end;
|
|
||||||
} else {
|
} else {
|
||||||
log::debug!("LAST WITH NO MARKUP");
|
log::debug!("LAST WITH NO MARKUP");
|
||||||
page += p.text.slice(cur..);
|
content += p.text.slice(cur..);
|
||||||
if no_render_html {
|
|
||||||
page = page.replace("<", "<").replace(">", ">");
|
|
||||||
}
|
|
||||||
content += &page;
|
|
||||||
content += &Markup::end(p, pindex, &mut state);
|
content += &Markup::end(p, pindex, &mut state);
|
||||||
}
|
}
|
||||||
paragraphs.push(content);
|
paragraphs.push(content);
|
||||||
|
|
40
src/proxy.rs
40
src/proxy.rs
|
@ -133,7 +133,7 @@ const INDEX: &str = include_str!("../templates/index.html");
|
||||||
async fn index() -> impl Responder {
|
async fn index() -> impl Responder {
|
||||||
HttpResponse::Ok()
|
HttpResponse::Ok()
|
||||||
.content_type("text/html; charset=utf-8")
|
.content_type("text/html; charset=utf-8")
|
||||||
.body(INDEX.replace("SOURCE_CODE_REPLACE", &crate::SETTINGS.source_code))
|
.body(INDEX)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_web_codegen_const_routes::get(path = "crate::V1_API_ROUTES.proxy.asset")]
|
#[actix_web_codegen_const_routes::get(path = "crate::V1_API_ROUTES.proxy.asset")]
|
||||||
|
@ -158,33 +158,29 @@ async fn assets(path: web::Path<String>, data: AppData) -> impl Responder {
|
||||||
|
|
||||||
#[actix_web_codegen_const_routes::get(path = "crate::V1_API_ROUTES.proxy.by_post_id")]
|
#[actix_web_codegen_const_routes::get(path = "crate::V1_API_ROUTES.proxy.by_post_id")]
|
||||||
async fn by_post_id(path: web::Path<String>, data: AppData) -> impl Responder {
|
async fn by_post_id(path: web::Path<String>, data: AppData) -> impl Responder {
|
||||||
match data.get_post_light(&path).await {
|
let post_data = data.get_post_light(&path).await;
|
||||||
None => HttpResponse::NotFound().body("Post not found"),
|
HttpResponse::Found()
|
||||||
Some(post_data) => HttpResponse::Found()
|
.append_header((
|
||||||
|
header::LOCATION,
|
||||||
|
crate::V1_API_ROUTES
|
||||||
|
.proxy
|
||||||
|
.get_page(&post_data.username, &post_data.slug),
|
||||||
|
))
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_web_codegen_const_routes::get(path = "crate::V1_API_ROUTES.proxy.top_level_post")]
|
||||||
|
async fn by_top_level_post(path: web::Path<String>, data: AppData) -> impl Responder {
|
||||||
|
if let Some(post_id) = path.split('-').last() {
|
||||||
|
let post_data = data.get_post_light(post_id).await;
|
||||||
|
HttpResponse::Found()
|
||||||
.append_header((
|
.append_header((
|
||||||
header::LOCATION,
|
header::LOCATION,
|
||||||
crate::V1_API_ROUTES
|
crate::V1_API_ROUTES
|
||||||
.proxy
|
.proxy
|
||||||
.get_page(&post_data.username, &post_data.slug),
|
.get_page(&post_data.username, &post_data.slug),
|
||||||
))
|
))
|
||||||
.finish(),
|
.finish()
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[actix_web_codegen_const_routes::get(path = "crate::V1_API_ROUTES.proxy.top_level_post")]
|
|
||||||
async fn by_top_level_post(path: web::Path<String>, data: AppData) -> impl Responder {
|
|
||||||
if let Some(post_id) = path.split('-').last() {
|
|
||||||
match data.get_post_light(post_id).await {
|
|
||||||
None => HttpResponse::NotFound().body("Post not found"),
|
|
||||||
Some(post_data) => HttpResponse::Found()
|
|
||||||
.append_header((
|
|
||||||
header::LOCATION,
|
|
||||||
crate::V1_API_ROUTES
|
|
||||||
.proxy
|
|
||||||
.get_page(&post_data.username, &post_data.slug),
|
|
||||||
))
|
|
||||||
.finish(),
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
HttpResponse::NotFound().body("Post not found, please file bug report")
|
HttpResponse::NotFound().body("Post not found, please file bug report")
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ pub struct SourcegraphQuery<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SourcegraphQuery<'a> {
|
impl<'a> SourcegraphQuery<'a> {
|
||||||
pub fn syntax_highlight(&self, gist_name: &str) -> String {
|
pub fn syntax_highlight(&self) -> String {
|
||||||
// let ss = SYNTAX_SET;
|
// let ss = SYNTAX_SET;
|
||||||
let ts = ThemeSet::load_defaults();
|
let ts = ThemeSet::load_defaults();
|
||||||
|
|
||||||
|
@ -66,8 +66,7 @@ impl<'a> SourcegraphQuery<'a> {
|
||||||
if line_num == 0 || line_num == total_lines - 1 {
|
if line_num == 0 || line_num == total_lines - 1 {
|
||||||
output.push_str(line);
|
output.push_str(line);
|
||||||
} else {
|
} else {
|
||||||
let line_id = format!("{gist_name}-{num}");
|
output.push_str(&format!("<div title='click for more options' id=\"line-{num}\"class=\"line\"><details class='line_links'><summary class='line_top-link'><a href=\"#line-{num}\"<span class=\"line-number\">{num}</span></a>{line}</summary><a href=\"#line-{num}\"<span class=\"line-link\">Permanant link</span></a><a href=\"#line-{num}\"<span class=\"line-link\">Highlight</span></a></details></div>"
|
||||||
output.push_str(&format!("<div title='click for more options' id=\"line-{line_id}\"class=\"line\"><details class='line_links'><summary class='line_top-link'><a href=\"#line-{line_id}\"<span class=\"line-number\">{num}</span></a>{line}</summary><a href=\"#line-{line_id}\"<span class=\"line-link\">Permanant link</span></a><a href=\"#line-{line_id}\"<span class=\"line-link\">Highlight</span></a></details></div>"
|
|
||||||
));
|
));
|
||||||
num += 1;
|
num += 1;
|
||||||
}
|
}
|
||||||
|
@ -154,7 +153,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
let result = query.determine_language(&syntax_set);
|
let result = query.determine_language(&syntax_set);
|
||||||
assert_eq!(result.name, "TeX");
|
assert_eq!(result.name, "TeX");
|
||||||
let _result = query.syntax_highlight("foo");
|
let _result = query.syntax_highlight();
|
||||||
}
|
}
|
||||||
|
|
||||||
//#[test]
|
//#[test]
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
href="/@tylerneely/fear-and-loathing-in-lock-free-programming-7158b1cdd50c"
|
href="/@tylerneely/fear-and-loathing-in-lock-free-programming-7158b1cdd50c"
|
||||||
>Demo Article</a
|
>Demo Article</a
|
||||||
>
|
>
|
||||||
| <a href="SOURCE_CODE_REPLACE">Source Code</a>
|
| <a href="https://github.com/realaravinth/libmedium">Source Code</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
body {
|
body {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue