前言
Flomo 是一款非常简洁简单的记录软件,它之所以能够在各种平台中记录你的笔记,是因为它简洁的API让很多开发者很容易地集成到各种软件上。
curl -X POST https://flomoapp.com/iwh/xxx/xxxx/ \
-H "Content-type: application/json" \
-d '{
"content": "Hello, #flomo https://flomoapp.com"
}'
目前我常用的插件是raycast扩展,它能让我在电脑前有灵感的时候快速呼出raycast,记录并直接保存。
还有一个常用的插件是 flomoplus,它的功能非常多。能对网页本身进行美化,也支持多平台导入,当然它也能直接将网页保存到flomo中,作为书签
目前我所使用的书签管理服务是 cubox。但是这款工具我只会不断地将书签保存进去,没有主动打开的习惯,它只作为我的书签保存器,基于这个需求,原网页的快照功能基本上我也用不到,因此 flomo 完全可以替代这个工具。看到 cubox 的年费定价和 flomo 的年费定价相差无几,于是决定以后使用 flomo 来做标签管理
遇到的问题
看到 flomoplus 这个功能的时候,这个工具已经大部分满足我的需求。它能够使用上下文菜单直接发送到 flomo 中,也可以点击扩展图片呼出输入框来编辑笔记后发送,但是对于我的使用场景有几个遇到的问题:
- 无法按照我的格式要求修改排版
- 我需要将bookmark作为一级标签,然后再使用网站域名作为二级标签,这样书签能够在bookmark下同一管理,flomoplus 需要自己修改二级标签,比较不方便。
发现这个问题后,便去搜索一下 flomoplus 是否开源,如果开源的话,就打算在它基础上针对我的需求修改代码再使用。比较遗憾的是,这个插件在 Github 上只上传了一个zip包,源码并没有直接开源。
鉴于以上原因,因此想自己开发一个插件来满足自己的需求。
flomo-bookmark flomo书签
作为一个后端开发工程师,想要在前端样式上做出好看的排版也比较困难,目前这个插件正在审核中,功能只是实现了最基本的功能,样式会在后面的版本中进行优化。 这里主要谈谈使用到的技术与功能的部分实现,后续的功能介绍放在后面的文章中。
技术栈 - 脚手架选型
对于比较有限的前端基础的我来说,页面开发、打包还是比较困难的。于是在 Github 上找一下有没有比较好的脚手架,发现了在 awesome-vite 列表中发现了这个脚手架 chrome-extension-boilerplate-react-vite 。列出使用的技术栈:
- React 18
- Typescript
- Vite
React 是我目前会用的前端框架, Typescript 能够帮助我避免 Javascript 可能遇到的奇怪原因,Vite 可以在开发过程中更加快速的调试。于是就选定这个脚手架进行开发。
UI 框架 - chakra-ui
在这个脚手架中有两个样式方案 Twind 和 Chakra-ui,想着快速开发,便直接使用了 Chakra-ui 来做,这里有关于它的简单教程 chakra for beginners
获取当前页面的链接与标题 - chrome api
这个插件的核心就是获取当前页面的链接与标题,可以在这里找到对应的API chrome.api.tabs
写成代码则是
export function getCurrentTabInfo(): Promise<{ title: string; url: string }> {
return new Promise((resolve, reject) => {
chrome.tabs.query({ active: true, currentWindow: true }, tabs => {
if (tabs[0]) {
const { title, url } = tabs[0];
resolve({ title, url });
} else {
reject("No active tab found");
}
});
});
}
获取域名信息 - 求助 Github Pilot Chat
本来是打算在 npmjs 来获取一个依赖来完成这个小需求,找到了 getdomain,看他的更新日期在五年前了,就打算试试问一下 Github Pilot Chat,结果可以直接拿来用
export function getDomainFromUrl(url: string): string {
try {
const parsedUrl = new URL(url);
const domain = parsedUrl.hostname;
const parts = domain.split(".");
const tld = parts.pop(); // 顶级域名(例如.com、.org等)
const secondLevelDomain = parts.pop(); // 二级域名
if (secondLevelDomain && tld) {
return `${secondLevelDomain}.${tld}`;
} else {
return domain;
}
} catch (error) {
// 处理无效URL的情况
console.error("Invalid URL:", url);
return "";
}
}
整合数据发送请求 - 结束
附上使用 fetch 来调用 flomo 的接口,这样就完成了发送请求了(里面包含了chakra-ui的toast组件)
fetch(apiConfig.api, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
.then(res => res.json())
.then(data => {
console.log(data);
setLoading(false);
if (data["code"] === -1) {
toast({
title: "发送失败",
description: data["message"],
status: "error",
duration: 9000,
isClosable: true,
});
} else {
toast({
title: "发送成功",
description: "请在flomo中查看你保存的书签",
status: "success",
duration: 3000,
isClosable: true,
});
}
})
.catch(error => {
console.log(error);
setLoading(false);
toast({
title: "发送失败",
description: "请确定你的API 设置正确,或检查网络是否正常",
status: "error",
duration: 9000,
isClosable: true,
});
});