Add hashnode support for posts plugin and additional options (#165)
This commit is contained in:
23
source/app/mocks/api/axios/post/hashnode.mjs
Normal file
23
source/app/mocks/api/axios/post/hashnode.mjs
Normal file
@@ -0,0 +1,23 @@
|
||||
/**Mocked data */
|
||||
export default function({faker, url, body, login = faker.internet.userName()}) {
|
||||
if (/^https:..api.hashnode.com.*$/.test(url)) {
|
||||
console.debug(`metrics/compute/mocks > mocking hashnode result > ${url}`)
|
||||
return ({
|
||||
status:200,
|
||||
data:{
|
||||
data:{
|
||||
user:{
|
||||
publication:{
|
||||
posts:new Array(30).fill(null).map(_ => ({
|
||||
title:faker.lorem.sentence(),
|
||||
brief:faker.lorem.paragraph(),
|
||||
coverImage:null,
|
||||
dateAdded:faker.date.recent(),
|
||||
})),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -344,9 +344,13 @@
|
||||
...(set.plugins.enabled.posts ? ({
|
||||
posts:{
|
||||
source:options["posts.source"],
|
||||
descriptions:options["posts.descriptions"],
|
||||
covers:options["posts.covers"],
|
||||
list:new Array(Number(options["posts.limit"])).fill(null).map(_ => ({
|
||||
title:faker.lorem.sentence(),
|
||||
date:faker.date.recent().toString().substring(4, 10).trim()
|
||||
description:faker.lorem.paragraph(),
|
||||
date:faker.date.recent(),
|
||||
image:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mOcOnfpfwAGfgLYttYINwAAAABJRU5ErkJggg==",
|
||||
}))
|
||||
}
|
||||
}) : null),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//Setup
|
||||
export default async function({login, data, imports, q, account}, {enabled = false} = {}) {
|
||||
export default async function({login, data, imports, q, queries, account}, {enabled = false} = {}) {
|
||||
//Plugin execution
|
||||
try {
|
||||
//Check if plugin is enabled and requirements are met
|
||||
@@ -7,7 +7,7 @@
|
||||
return null
|
||||
|
||||
//Load inputs
|
||||
let {source, limit, user} = imports.metadata.plugins.posts.inputs({data, account, q})
|
||||
let {source, descriptions, covers, limit, user} = imports.metadata.plugins.posts.inputs({data, account, q})
|
||||
|
||||
//Retrieve posts
|
||||
console.debug(`metrics/compute/${login}/plugins > posts > processing with source ${source}`)
|
||||
@@ -16,7 +16,12 @@
|
||||
//Dev.to
|
||||
case "dev.to":{
|
||||
console.debug(`metrics/compute/${login}/plugins > posts > querying api`)
|
||||
posts = (await imports.axios.get(`https://dev.to/api/articles?username=${user}&state=fresh`)).data.map(({title, readable_publish_date:date}) => ({title, date}))
|
||||
posts = (await imports.axios.get(`https://dev.to/api/articles?username=${user}&state=fresh`)).data.map(({title, description, published_at:date, cover_image:image}) => ({title, description, date, image}))
|
||||
break
|
||||
}
|
||||
//Hashnode
|
||||
case "hashnode":{
|
||||
posts = (await imports.axios.post("https://api.hashnode.com", {query:queries.posts.hashnode({user})}, {headers:{"Content-type":"application/json"}})).data.data.user.publication.posts.map(({title, brief:description, dateAdded:date, coverImage:image}) => ({title, description, date, image}))
|
||||
break
|
||||
}
|
||||
//Unsupported
|
||||
@@ -26,13 +31,18 @@
|
||||
|
||||
//Format posts
|
||||
if (Array.isArray(posts)) {
|
||||
//Limit tracklist
|
||||
//Limit posts
|
||||
if (limit > 0) {
|
||||
console.debug(`metrics/compute/${login}/plugins > posts > keeping only ${limit} posts`)
|
||||
posts.splice(limit)
|
||||
}
|
||||
//Cover images
|
||||
if (covers) {
|
||||
console.debug(`metrics/compute/${login}/plugins > posts > formatting cover images`)
|
||||
posts = await Promise.all(posts.map(async({image, ...post}) => ({image:await imports.imgb64(image, {width:144, height:-1}), ...post})))
|
||||
}
|
||||
//Results
|
||||
return {source, list:posts}
|
||||
return {source, descriptions, covers, list:posts}
|
||||
}
|
||||
|
||||
//Unhandled error
|
||||
|
||||
@@ -19,6 +19,19 @@ inputs:
|
||||
default: ""
|
||||
values:
|
||||
- dev.to # Dev.to
|
||||
- hashnode
|
||||
|
||||
# Display a few lines about each posts
|
||||
plugin_posts_descriptions:
|
||||
description: Display posts descriptions
|
||||
type: boolean
|
||||
default: no
|
||||
|
||||
# Display posts cover images
|
||||
plugin_posts_covers:
|
||||
description: Display posts cover images
|
||||
type: boolean
|
||||
default: no
|
||||
|
||||
# Number of posts to display
|
||||
plugin_posts_limit:
|
||||
|
||||
12
source/plugins/posts/queries/hashnode.graphql
Normal file
12
source/plugins/posts/queries/hashnode.graphql
Normal file
@@ -0,0 +1,12 @@
|
||||
query PostsHashnode {
|
||||
user(username: "$user"){
|
||||
publication{
|
||||
posts(page: 1) {
|
||||
title
|
||||
brief
|
||||
coverImage
|
||||
dateAdded
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,3 +5,11 @@
|
||||
plugin_posts: yes
|
||||
plugin_posts_source: dev.to
|
||||
plugin_posts_user: lowlighter
|
||||
|
||||
- name: Posts plugin (hashnode)
|
||||
uses: lowlighter/metrics@latest
|
||||
with:
|
||||
token: NOT_NEEDED
|
||||
plugin_posts: yes
|
||||
plugin_posts_source: hashnode
|
||||
plugin_posts_user: lowlighter
|
||||
|
||||
@@ -17,12 +17,22 @@
|
||||
From <%= plugins.posts.source %>
|
||||
</div>
|
||||
<% if (plugins.posts.list.length) { %>
|
||||
<% for (const {title, date} of plugins.posts.list) { %>
|
||||
<% for (const {title, description, image, date} of plugins.posts.list) { %>
|
||||
<div class="field post">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M4.75 0a.75.75 0 01.75.75V2h5V.75a.75.75 0 011.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0113.25 16H2.75A1.75 1.75 0 011 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 014.75 0zm0 3.5h8.5a.25.25 0 01.25.25V6h-11V3.75a.25.25 0 01.25-.25h2zm-2.25 4v6.75c0 .138.112.25.25.25h10.5a.25.25 0 00.25-.25V7.5h-11z"></path></svg>
|
||||
<div class="infos">
|
||||
<div class="date"><%= date %></div>
|
||||
<div class="title"><%= title %></div>
|
||||
<div class="left">
|
||||
<div class="date"><%= f.date(new Date(date), {dateStyle:"short"}) %></div>
|
||||
<% if (plugins.posts.covers) { %>
|
||||
<div class="cover" style="background-image: url(<%= image %>);"></div>
|
||||
<% } %>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="title"><%= title %></div>
|
||||
<% if (plugins.posts.descriptions) { %>
|
||||
<div class="description"><%= description %></div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
@@ -287,20 +287,43 @@
|
||||
display: flex;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.post .infos .title {
|
||||
font-size: 14px;
|
||||
width: 380px;
|
||||
white-space: normal;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-height: 40px;;
|
||||
}
|
||||
.post .infos .date {
|
||||
.post .infos .left {
|
||||
flex-shrink: 0;
|
||||
font-size: 12px;
|
||||
color: #666666;
|
||||
width: 60px;
|
||||
width: 72px;
|
||||
padding-top: 1px;
|
||||
text-align: center;
|
||||
}
|
||||
.post .infos .cover {
|
||||
width: 100%;
|
||||
height: 56px;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.post .infos .right {
|
||||
width: 376px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
.post .infos .title, .post .infos .description {
|
||||
font-size: 14px;
|
||||
white-space: normal;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-height: 38px;
|
||||
/* May not work in all browsers */
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
.post .infos .description {
|
||||
margin-top: 3px;
|
||||
font-size: 12px;
|
||||
max-height: 48px;
|
||||
color: #666666;
|
||||
-webkit-line-clamp: 3;
|
||||
}
|
||||
|
||||
/* Topics */
|
||||
|
||||
Reference in New Issue
Block a user