halo-dev / halo

强大易用的开源建站工具。
https://www.halo.run
GNU General Public License v3.0
34.01k stars 9.7k forks source link

建议丰富文章中的链接展示形式 #5650

Closed xiaodunxin closed 4 months ago

xiaodunxin commented 7 months ago

你当前使用的版本

2.14.0

描述一下此特性

建议文章的链接可以用卡片的展示形式,这样比较美观,可参考飞书: image

附加信息

No response

ruibaby commented 7 months ago

感谢反馈,这个功能看起来确实很有用,但需要讨论一下实现方式。

/area ui /area editor /kind feature

AeroWang commented 7 months ago

可以看看 Puppeteer 或者 Selenium ?

其中预览视图可以通过 Puppeteer 截图实现。这个我觉得应该是通过插件实现一个服务,编辑器可以使用,主题也可以使用

ruibaby commented 7 months ago

可以看看 Puppeteer 或者 Selenium ?

其中预览视图可以通过 Puppeteer 截图实现。这个我觉得应该是通过插件实现一个服务,编辑器可以使用,主题也可以使用

通常做法是解析到 OpenGraph 这些数据就行了吧。

AeroWang commented 7 months ago

单纯放在前端处理有可能会跨域。预览视图需要截图预览实现了

AeroWang commented 7 months ago

这里有一个 Node 服务实现

const express = require('express');
const puppeteer = require('puppeteer');
const bodyParser = require('body-parser')
const app =express();

app.use(bodyParser.urlencoded({
    extended:true
}))
app.use(bodyParser.json())

app.get('/',async function (req,res){
    const url = req.query.url;
    //加载浏览器
    const browser = await puppeteer.launch({
        headless: 'shell',
        devtools: false,
        args: ['--devtools-flags=disable'],
    });
    //打开空白页
    const page = await browser.newPage();
    await page.goto(url,{
        //等待网页都加载完
        waitUntil:'domcontentloaded'
    });

    const info = await page.evaluate(()=>{
        //获取网页描述信息<meta name="description"></meta>
        const descMetaEl = document.querySelector('meta[name="description"]');
        const desc = descMetaEl?.getAttribute('content') ?? '';
        //icon
        const icon = document.querySelector('link[rel*="icon"]')?.getAttribute('href') ?? '';
        //网站的主机名
        const host = window.location.host;
        const baseUrl = window.location.protocol + '//' + host;
        return { desc, icon, host, baseUrl };
    })
    await page.setViewport({ width: 150, height: 100 });
    //网站的标题
    const title = await page.title();
    const theUrl = page.url();
    //用完关闭浏览器
    await browser.close();
    const data ={
        title,
        url:theUrl,
        desc:info.desc,
        icon: getIcon(info.icon, info.baseUrl),
        host: info.host,
        baseUrl: info.baseUrl,
    }

    res.send(data)

})

app.listen(3000,()=>{
    console.log('listen on 3000 successfully!')
})

//需要进一步处理icon的路径,有些icon链接可以直接访问,有一些可能是相对路径
function getIcon(url, baseUrl) {
    if (!url || /^http(s)*/.test(url)) return url;
    if (url.startsWith('/')) {
        return baseUrl + url;
    }
    if (url.startsWith('./')) {
        return baseUrl + url.substring(1, url.length);
    }
    return baseUrl + '/' + url;
}
ruibaby commented 7 months ago

使用 puppeteer 这种服务去截图太重了,也不是常见做法,这种卡片优先都是取 OpenGraph 这些元数据,包括目前主要社交软件(比如 Slack、X)都是采用的这种做法。包括 issue 当中的截图也是拿到的 GitHub 提供的 OpenGraph 图片。

image
AeroWang commented 7 months ago

使用 puppeteer 这种服务去截图太重了,也不是常见做法,这种卡片优先都是取 OpenGraph 这些元数据,包括目前主要社交软件(比如 Slack、X)都是采用的这种做法。包括 issue 当中的截图也是拿到的 GitHub 提供的 OpenGraph 图片。

image

有些站点有可能没有这些 OpenGraph 元数据。通过简单的 description, icon, title等字段也是可以的,不需要截图的话有可能有其它比较轻量的方法,我还没想到

ruibaby commented 7 months ago

有些站点有可能没有这些 OpenGraph 元数据。通过简单的 description, icon, title等字段也是可以的,不需要截图的话有可能有其它比较轻量的方法,我还没想到

可以按照先后顺序,如果没有 OpenGraph,可以直接取网页的 title description 等,图片也可以取 link[rel="icon"] 等,如果实在没有找到任何图片,那也可以不显示。我认为去调用服务截图始终是一个耗费资源,效果还不好(图片尺寸控制,因为这种卡片不可能显示大图)的方式。

原 issue 作者提到的飞书对于不同场景的做法:

image

单纯放在前端处理有可能会跨域。

可以通过插件提供接口,这个接口只需要解析这些数据然后返回给前端。前端我推荐采用 Lit 这种构建为 Web Component 组件的框架,可以非常方便的嵌入到编辑器和主题文章页面。

AeroWang commented 7 months ago

服务可以直接请求对应链接的网页内容字符串,直接取出对应字段的值。这种可能就做不到 image 这种预览截图

AeroWang commented 7 months ago

可惜我不会Java,留给有兴趣的人做吧🤣

ruibaby commented 7 months ago

服务可以直接请求对应链接的网页内容字符串,直接取出对应字段的值。这种可能就做不到 image 这种预览截图

这个图就不清楚飞书是怎么做的,至少不应该是截图,因为这个网站并没有这样的 UI,看起来像是生成的。

guqing commented 6 months ago

或许可以做个插件来试试 Portal 新提案用于显示链接网页内容,但这是个实验性的不受所有浏览器支持 https://web.dev/articles/hands-on-portals?hl=zh-cn https://developer.mozilla.org/en-US/docs/Web/HTML/Element/portal

AeroWang commented 6 months ago

或许可以做个插件来试试 Portal 新提案用于显示链接网页内容,但这是个实验性的不受所有浏览器支持 https://web.dev/articles/hands-on-portals?hl=zh-cn https://developer.mozilla.org/en-US/docs/Web/HTML/Element/portal

没发现,,,打不开

image
LIlGG commented 4 months ago

目前应用市场有 编辑器超链接卡片 插件,可以用来实现此需求。此插件可以在默认编辑器中,将普通链接转为卡片的形式。可以试试。

/close

f2c-ci-robot[bot] commented 4 months ago

@LIlGG: Closing this issue.

In response to [this](https://github.com/halo-dev/halo/issues/5650#issuecomment-2172126874): >目前应用市场有 [编辑器超链接卡片](https://www.halo.run/store/apps/app-UpUJA) 插件,可以用来实现此需求。此插件可以在默认编辑器中,将普通链接转为卡片的形式。可以试试。 > >/close Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md). If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.