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 ? ({
|
...(set.plugins.enabled.posts ? ({
|
||||||
posts:{
|
posts:{
|
||||||
source:options["posts.source"],
|
source:options["posts.source"],
|
||||||
|
descriptions:options["posts.descriptions"],
|
||||||
|
covers:options["posts.covers"],
|
||||||
list:new Array(Number(options["posts.limit"])).fill(null).map(_ => ({
|
list:new Array(Number(options["posts.limit"])).fill(null).map(_ => ({
|
||||||
title:faker.lorem.sentence(),
|
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),
|
}) : null),
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//Setup
|
//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
|
//Plugin execution
|
||||||
try {
|
try {
|
||||||
//Check if plugin is enabled and requirements are met
|
//Check if plugin is enabled and requirements are met
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
return null
|
return null
|
||||||
|
|
||||||
//Load inputs
|
//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
|
//Retrieve posts
|
||||||
console.debug(`metrics/compute/${login}/plugins > posts > processing with source ${source}`)
|
console.debug(`metrics/compute/${login}/plugins > posts > processing with source ${source}`)
|
||||||
@@ -16,7 +16,12 @@
|
|||||||
//Dev.to
|
//Dev.to
|
||||||
case "dev.to":{
|
case "dev.to":{
|
||||||
console.debug(`metrics/compute/${login}/plugins > posts > querying api`)
|
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
|
break
|
||||||
}
|
}
|
||||||
//Unsupported
|
//Unsupported
|
||||||
@@ -26,13 +31,18 @@
|
|||||||
|
|
||||||
//Format posts
|
//Format posts
|
||||||
if (Array.isArray(posts)) {
|
if (Array.isArray(posts)) {
|
||||||
//Limit tracklist
|
//Limit posts
|
||||||
if (limit > 0) {
|
if (limit > 0) {
|
||||||
console.debug(`metrics/compute/${login}/plugins > posts > keeping only ${limit} posts`)
|
console.debug(`metrics/compute/${login}/plugins > posts > keeping only ${limit} posts`)
|
||||||
posts.splice(limit)
|
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
|
//Results
|
||||||
return {source, list:posts}
|
return {source, descriptions, covers, list:posts}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Unhandled error
|
//Unhandled error
|
||||||
|
|||||||
@@ -19,6 +19,19 @@ inputs:
|
|||||||
default: ""
|
default: ""
|
||||||
values:
|
values:
|
||||||
- dev.to # Dev.to
|
- 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
|
# Number of posts to display
|
||||||
plugin_posts_limit:
|
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: yes
|
||||||
plugin_posts_source: dev.to
|
plugin_posts_source: dev.to
|
||||||
plugin_posts_user: lowlighter
|
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 %>
|
From <%= plugins.posts.source %>
|
||||||
</div>
|
</div>
|
||||||
<% if (plugins.posts.list.length) { %>
|
<% 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">
|
<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>
|
<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="infos">
|
||||||
<div class="date"><%= date %></div>
|
<div class="left">
|
||||||
<div class="title"><%= title %></div>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|||||||
@@ -287,20 +287,43 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
}
|
}
|
||||||
.post .infos .title {
|
.post .infos .left {
|
||||||
font-size: 14px;
|
|
||||||
width: 380px;
|
|
||||||
white-space: normal;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
max-height: 40px;;
|
|
||||||
}
|
|
||||||
.post .infos .date {
|
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #666666;
|
color: #666666;
|
||||||
width: 60px;
|
width: 72px;
|
||||||
padding-top: 1px;
|
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 */
|
/* Topics */
|
||||||
|
|||||||
Reference in New Issue
Block a user