Spaces:
Running
Running
File size: 2,698 Bytes
4711c0c |
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
from fasthtml.common import *
from fastcore.net import urlparse
import httpx
app, rt = fast_app(pico=False, hdrs=(Link(href='style.css', rel='stylesheet'),))
async def fetch_get(url):
async with httpx.AsyncClient() as client:
response = await client.get(url)
response.raise_for_status()
return response.json()
def NavTop(back=False):
return Div(
Div(
Div(
Img(src="https://news.ycombinator.com/y18.svg", cls="logo"),
A(B('Hacker News'), href='./'),
A(NotStr(' << back'), href="./") if back else None,
cls='header-content'
),
A('code', href="https://github.com/pratapvardhan/hackernews-fasthtml"),
cls='header-content space-between'),
cls='header')
def HomeRow(data, n='', pl=True):
domain = urlparse(data['url']).netloc
link = f'./item?id={data["id"]}'
return Div(
Div(
Span(f'{n}.' if n else None),
A(data['title'], href=data['url'], cls='st-t'),
Span(f'({domain})', cls='st-d') if domain else None,
cls='st'),
Div(
f'{data["points"]} points by', A(data['user']),
A(data['time_ago'], href=link), ' | ', A(f'{data["comments_count"]} comments', href=link),
cls=f"st-sub {'pl-15p' if pl else ''}"),
cls='st'
)
def Comment(data):
return Div(
Div(f"• {data.get('user', '[deleted]')} {data['time_ago']}", cls='st-sub'),
Div(NotStr(data['content']), cls='st-c'),
*map(Comment, data['comments']),
cls='st-cb',
style=f"margin-left: {'20px' if data['level'] else 0};",
)
def ScrollMore(page):
return Div('Scroll for more..', hx_get=f"/?page={page}", hx_trigger="intersect once", hx_swap="outerHTML", hx_target="this", cls='st-c')
async def Feed(page=1, top=True):
sno = (page - 1) * 30 + 1
data = await fetch_get(f"https://node-hnapi.herokuapp.com/news?page={page}")
return *[HomeRow(d, n) for n, d in enumerate(data, sno)], ScrollMore(page+1)
@rt("/")
async def get(page: int = 1):
content = await Feed(page, top=(page == 1))
return Div(NavTop(), Div(*content, cls='content'), cls='container') if page == 1 else content
@rt("/item")
async def get(id:int):
data = await fetch_get(f"https://node-hnapi.herokuapp.com/item/{id}")
return Div(
NavTop(back=True),
Div(
HomeRow(data, n='', pl=False),
Div(NotStr(data.get('content', '')), cls='st-g'), Br(),
*map(Comment, data['comments']),
style='padding:0 15px;'
),
cls='container'
)
serve() |