标签 Typecho 下的文章

"前车之鉴"-再造车轮Typecho_Plugin


前言

这是基于SweetAlert2伪实现的typecho图片放大效果的插件,因为之前发现博客里插入图片之后,它默认不能放大,而我虽然用的是笔记本电脑,但是电脑显示里的缩放与布局我不习惯用它推荐的125%,而是用了传统的100%,这就在浏览一些博客的时候显得主体内容比较小巧。我看了其他的一些博客平台,但凡是插入图片的,双击一下图片就会增大显示,这也算是个基本功能吧,但不知道是因为主题原因还是啥,我的博客就不行,自己先前在网上找过类似的插件,比如说梁先生制作的pScaleUp插件,能应对大多数typecho主题,但是我使用的这一款GreenGrapes主题却不是那么的理想,在启用这款插件时,在文章里试了下,发现图片确实被放大了,但是却被局限在容器里,因为在当前主题设定的文章内容主题容器有一个css属性 overflow: hidden;,这就导致了上述问题,本着不影响原先主题源代码并适当增加效果的选择性与美观性,就想着要不在尝试着再写一个简单的插件?因为之前写过一个,这次就是把轮子拿过来直接照葫芦画瓢就行,也不怎么麻烦。说干就干……

实现功能

  • 启用后进入的设置页面(因为我的主题配绿色会比较协调,所以选择了纯净绿)

设置页面.png

  • 按照上示设置后的页面效果(以我上一篇博客内的图片为例)

放大效果示例.png

  • 启用方法

git clone至plugins文件夹下并修改文件名为ExImg,后台启用并进入设置打开即可。
单击放大后图片的外部即可取消放大效果
git地址

过程

如何实现放大的效果我想了一下,之前基于SweetAlert实现过表白的弹窗效果,感觉效果还不错,以前用的是是这个官网的,但是相比起来SweetAlert2中的功能要更加完善一点(但我个人觉得从弹窗的美观性上来讲不如上一个)。后者可以自定义弹窗(alert)的图标和大小,并且只传入一个url即可,原先我暂定是使用向弹窗中插入HTML代码块实现显示image的功能,但是实际做了一下发现效果并不怎么样,索性还是直接用它的图标属性吧,还可以设置自定义图标的CSS类,对于这一句我开始以为能直接在里面写CSS属性,结果最后发现是能够指定类名,汗……然后他那个弹窗的宽高和边框的大小可以自己设定,然后我就根据给图片设置的大小来设定了,保证其美观性。还有背景颜色(themes)这一功能非常讨人喜欢,然后我就简单加了三种可以选项的颜色,分别是幻影紫、纯净绿和暖心红(后续还会添加令人愉悦的颜色选择)。名字当然是我自己瞎起的……然后图片的选择用了jQuery的双击监听事件,确保了双击的标签是img后才显示放大效果。目前看来所有的一切顺利进行。但是我这个憨憨在仿制车轮的时候又翻车了,反正开始以为遇到玄学问题了,实在忍不住了还反问它:我与阁下无冤无仇,为何你却要把我的智商按在地上摩擦?……我先简单说一下这个伪玄学~

当时表单正常传过来值之后我便在下边判断了值的类型与value,确保准确无误后以传参的形式传给了handleImgExType()

$expandImgType = Typecho_Widget::widget('Widget_Options')->plugin('ExImg')->expandImgType;
$expandImgBgType = Typecho_Widget::widget('Widget_Options')->plugin('ExImg')->expandImgBgType;
if ($expandImgType != 'default') {
    self::handleImgExType($expandImgType, $expandImgBgType);
}

这没错吧?看下边……

private static function handleImgExType($$expandImgType, $$expandImgBgType){}

我也想不起哪里多打了个$符,导致传过来的是null,而swal({})接收到的参数如果有Null的时候,他不执行,而且还不给你报错?具体也忘了什么情况的时候不报错但也不运行来着……害的我一点点的调试,看看click事件能否监听正常,dblclick事件能否监听正常,那还用说么?当然得正常了,但是我一加入下方的其他有关调控alertJS代码后就完全没反应了,WDFK!!!玄学???在本地运行的好好的,肿么又不行了……最后还是没发现问题,将属性值写死后才发现正常运行,终于出现了久违的alert当即发现传参的问题,但是传参在第一步就已经检查过了没问题呀?然后在传进参数的函数里又var_dump()了一下参数,双双Null……仔细一看形参我写的是:

self::handleImgExType($$expandImgType, $$expandImgBgType);
private static function handleImgExType($$expandImgType, $$expandImgBgType){}

因为记不大清了哪写的多了$了,不是第一个就是第二个……

所谓玄学,云尔已矣,但确实挺刺激的……
于昨夜完成
其实吧,写这些东西主要是方便自己使用的,如果有幸入得了使用者的法眼,我也是蛮开心的(●'◡'●)


writing Typecho Plugin记录


前言

​ 自从我于2020-01-05(阳历)使用小马哥推荐的Typecho建立博客后(别看我建立博客之前还有文章发布,那都是之前写的随笔,被我从QQ空间的日志搬迁到了这里),就深深的被其精简化吸引,Typecho的插件也是多样,且能自主开发,能满足大部分人的需求,我感觉这样的社区氛围很赞。主题也一样,都可以自主开发,相比WordPress来说更加灵活,增加了使用者多元化选择的自由体验感。也就是最近几天,突然想要了解一下插件的实现,之前也粗略看过其他插件的code实现,但是当时不大了解Typecho的框架机制,所以也没看懂Plugin里的那些类接口到底干嘛的。今天心血来潮,整整试试吧,先弄个简单的,看看Plugin实现的coding流程...以后要什么效果如果可以的话,自己可以尝试写一下……

过程

​ 上午起来后花了一点时间把以前写的鼠标点击效果与图标跟随的代码翻了出来改了一下(以前用原生js写的,又给改成jQuery了),下午打开了几个我正在用的插件,想看看他们咋写的,应该就能推出那些接口干嘛的,参照了Typeho最初默认自带的那个Hello World插件,顺带打开了官方文档,因为Hello World 那个插件太简洁了,就完全是官方文档上介绍的那样。官方文档


先暂停,眼疼,明天再写,看了一天电脑了,吓人~先碎觉碎觉,狗命要紧~


主要是这部分:

2.注释

/**
 * Hello World
 *
 * @package HelloWorld
 * @author qining
 * @version 1.0.0
 * @link http://typecho.org
 */
  • Hello World: 插件描述
  • @package: 插件名称
  • @author: 插件作者
  • @version: 插件版本
  • @link: 插件作者链接

注释信息.png

因为他这个注释跟名称一样,所以说有点不明显,不过大体还是能看出来。

3.插件主体

/* 激活插件方法 */
public static function activate(){}

/* 禁用插件方法 */
public static function deactivate(){}

/* 插件配置方法 */
public static function config(Typecho_Widget_Helper_Form $form){}

/* 个人用户的配置方法 */
public static function personalConfig(Typecho_Widget_Helper_Form $form){}

/* 插件实现方法 */
public static function render(){}
  • activate: 插件的激活接口,主要填写一些插件的初始化程序。
  • deactivate: 这个是插件的禁用接口,主要就是插件在禁用时对一些资源的释放。
  • config: 插件的配置面板,用于制作插件的标准配置菜单。
  • personalConfig: 个人用户的配置面板,基本用不到。
  • render: 自己定义的方法,用来实现插件要完成的功能。

然后就没啥太重要的了,插件需要的一些东西放在config()里,Hello World插件的active()方法里放了这一句:

Typecho_Plugin::factory('admin/menu.php')->navBar = array('HelloWorld_Plugin', 'render');

​ 等号前边是接口代码,官方文档说复制进来就行,激活了用户管理那个面板,等号后边则是插件要实现的方法,这段代码会在接口处运行(也可以说是后台也启用了插件效果)。

// 当前接口的赋值以数组形式出现
// HelloWorld_Plugin 插件的类名,一般是插件名加上“_Plugin”,其中类名还可以用__CLASS__,不过经常是直接把插件类名写上
// render 插件实现的方法名,后面插件实现方法的命名要与此一致(当然你也可以改,不过一般不会改)

​ 因为我不仅要启用navBar,还需要向页面中添加css格式和js脚本(还是那句话,最简单的东西,熟悉一下流程),所以我将headerfooter也一块启用了:

public static function activate()
    {
        Typecho_Plugin::factory('Widget_Archive')->header = array(__CLASS__, 'header');
        Typecho_Plugin::factory('Widget_Archive')->footer = array(__CLASS__, 'footer');
        Typecho_Plugin::factory('admin/menu.php')->navBar = array('Mou_Plugin', 'render');
    }

​ 因为上边官方文档说类名类名还可以用__CLASS__ ,然后我就没改,其实原理都一样,只要后边把实现方法激活一下就行。

对于这个函数:

public static function deactivate(){}

​ 一般是在禁用插件时,需要释放的资源,我也没搞明白这个资源指的是啥,有关数据库之类的?用到的很少,也不敢说,我是用不着嘿嘿...

关键下边这个函数:

 public static function config(Typecho_Widget_Helper_Form $form)
{
    $name = new Typecho_Widget_Helper_Form_Element_Text('word', NULL, 'Hello World', _t('说点什么'));
    $form->addInput($name);
}
$form->addInput($name);

这句则是把定义的变量写入到配置项中,以便后面使用。

这是Hello World插件里的,没有什么实际作用,就是在插件设置里给你展示了一个表单:

hello设置.png

Typecho_Widget_Helper_Form这个类里还有一些别的我们如果要做开关之类的会用的到,比如说:

//mouseFollow开关
$options = [
     'default' => _t('关闭'),
     'paper' => "<img src='{$mouseFollowImageDir}/paper.ico' alt='paper'>",
  ];
$followType = new Typecho_Widget_Helper_Form_Element_Radio('followType', $options, 'default', _t('follow样式,默认关闭'));
$form->addInput($followType);

​ 先拿我的举个例子,Typecho_Widget_Helper_Form_Element_Radio他们都是继承自Typecho_Widget_Helper_Form_Element这个类的,这个父类的构造方法:

/**
     * 构造函数
     *
     * @access public
     * @param string $name 表单输入项名称
     * @param array $options 选择项
     * @param mixed $value 表单默认值
     * @param string $label 表单标题
     * @param string $description 表单描述
     * @return void
     */
public function __construct($name = NULL, array $options = NULL, $value = NULL, $label = NULL, $description = NULL)
{
    #code...
}

​ 我们可以看到第二个options行为参数需要传递一个数组,正好对应了选择项,$value可以填默认值,这样就可以给用户自己选择启不启用某一项功能,第一个参数和后边两个就好看了。

因为我在当前类里定义了一个常量

const STATIC_DIR = '/usr/plugins/Mou/static';

所以在config里再定义一下路径用来访问那个图标:

(这里和Helper::options()->pluginUrl这个方法效果一样,所以就没用着那个常量)

$dir = self::STATIC_DIR;
$staticDir = Helper::options()->pluginUrl . '/Mou/static/';
$mouseFollowImageDir = $staticDir . 'images';

这里的实现效果就是在设置的面板上显示出选项的图标:

图表显示.png

这里的路径要好好看看,如果显示不出来的话,用调试工具看看路径是不是多了或者少了一个/

之后便是人用户的配置方法:

/* 个人用户的配置方法 */
public static function personalConfig(Typecho_Widget_Helper_Form $form){}

不过在观察了几个插件的代码后发现基本都空着,所以我也空着了,上网查了一下:

public static function personalConfig(Typecho_Widget_Helper_Form $form) 插件的个性化配置面板。用法暂时还不明,有待Hanny进一步研究。

​ 我还是有空去看看源码,回头找着再补上吧~~话说回来,相关的官方文档太少了,网上搜出来的大多是一些个人博客里的东西。

接下来render

public static function render()
    {
        echo '<span class="message success">'
            . htmlspecialchars(Typecho_Widget::widget('Widget_Options')->plugin('HelloWorld')->word)
            . '</span>';
    }

函数里的内容便是要显示已经自定义好的欢迎话语。

Typecho_Widget::widget('Widget_Options')->plugin('HelloWorld')->word这句是调用插件配置项的,上边的配置项里有条这个:

$name = new Typecho_Widget_Helper_Form_Element_Text('word', NULL, 'Hello World', _t('说点什么'));
$form->addInput($name);

这里便是通过类的一些方法Typecho_Widget::widget('Widget_Options')->plugin('HelloWorld')->word提了出来。

​ 如果你仅仅是向页面中添加一点js脚本和css样式表,在你激活的herderfooter填写实现逻辑就行,可能有人会说就添加点cssjs而且,用得着小题大做弄个Plugin吗?我的回答还是一样,

  • 第一:熟悉一下Typecho Plugin的大体coding 流程
  • 第二:Typeho以其精简化深受光大用户的喜爱,我是完全可以直接在源码中扔进去cssjs但是这样对于Typecho日后升级更新啥的可能会影响到实现效果。这里的一个博主与我观点一致。

其原文内容如下(翻了半天历史记录才找着,汗~):

其实类似这种炫酷的鼠标插件一般借助CSSJS代码就可以实现,不过明月还是喜欢使用插件,毕竟插件实现的更稳定,兼容性也有保障,无论是升级Typecho还是主题都不会有太大的影响。

 /**
     *为header添加css文件
     * @return void
     */
    public static function header()
    {
        $StaticCssUrl = Helper::options()->pluginUrl . '/Mou/static/css/';
        echo '<link rel="stylesheet" href=" ' . $StaticCssUrl . 'style.css"/>';
    }

    /**
     *为footer添加js文件
     * @return void
     */
    public static function footer()
    {
        $dir = self::STATIC_DIR;
        $StaticJsUrl = Helper::options()->pluginUrl . '/Mou/static/js/';
        $followType = Typecho_Widget::widget('Widget_Options')->plugin('Mou')->followType;
        echo '<script type="text/javascript" src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>';
        $mouseFollowImageDir = $dir . '/images';
        // 调试部分
        // $test = 'test';
        // echo '<script type="text/javascript" src="' . $followType . $test . 'main.js"></script>';
        self::handleFollowType($followType);
        echo '<script type="text/javascript" src="' . $StaticJsUrl . 'main.js"></script>';
    }

这里看到还调用了一个函数handleFollowType()

/*mouseFollowStyle*/
    private static function handleFollowType($followType)
    {
        if ($followType != 'default') {
            $followTypeImage = $followType . '.ico';
            $dir = self::STATIC_DIR;
            $mouseFollowImagesDir = self::STATIC_DIR . '/images';
            $js .= '<script>';
            $js .= <<<JS
            $(document).ready(function () {
                $('body').append('<div id="followMouseContent"><img src="{$mouseFollowImagesDir}/{$followTypeImage}" alt="followMouse"></div>');
                $(document).mousemove(function (e) {
                var x = e.pageX;
                var y = e.pageY;
                var mms = document.getElementById('followMouseContent');
                var cx = parseInt(x) - parseInt(80);
                var cy = parseInt(y) + parseInt(10);
                mms.style.left = cx + "px";
                mms.style.top = cy + "px";
                });
            });
JS;
            $js .= '</script>';
            echo $js;
        } else {
            echo '';
        }
    }

这里主要是看看你的选择啦,要是不启用就没啥事了,启用的话判断一下你启用的图标。

这里调用的时候还犯了一个语法错误,用了$this->handleFollowType($followType)

PHP$thisself的区别 this是在实例化的时候来确定指向谁。 ... self是指向类本身,也就是self是不指向任何已经实例化的对象,一般self使用来指向类中的静态变量。

我怕不是个憨批……

现在流程说完了,要去后台启用看看生不生效。

​ 一般是没啥子问题,我这里却掉坑去了,其一便是上边那个self$this用混了,其二便是一个非常低级的错误……我写完后放在服务器的plugins文件夹下,启用没问题,但是那个图标选择却没生效,我又看了看逻辑没错啊,起初也是摸索着写,以为接口的一些参数东西还没整好,然后一顿查一顿看源码,没错啊肿末回事?反正做了一堆跟问题不搭边的事,还又把自己写的东西搞得一团乱麻,最后借助调试工具看了一下$followType = Typecho_Widget::widget('Widget_Options')->plugin('Mou')->followType;的传值,也没错啊,传的正确,但为何不顶用哪?条件判断也没错啊!不就是=某一项的时候选择哪一项嘛,咋还默认不启用了呢?WDFK!!!看出来了吧,我用的=来判断相不相等……赤果果的憨批一个真是心里上万只草泥马奔腾而过……这倒又让我想起来了前些日子练习Python爬虫,爬了猫眼电影的Top100榜,这个我也是醉了……我当时写了:

pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a'
                         +'.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>'
                         +'.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S)
items = re.findall(pattern, html)
for item in items:
    yield {
      'index': item[0],
      'image': item[1],
      'title': item[2],
      'actor': item[3].strip()[3:],
      'time': item[4].strip()[5:],
      'score': item[5]+item[6]
   }

​ 但是给我返回的 items 一直为空?嘛情况呀这是?正则语法错了?一查没嘚问题呀,而且错了会报错的吧,漏了条件?呃?不用 ^ 来标注起始呀……然后我又找了别的网站的源码,试着用正则提取一下,能提取出来也没问题啊,然后我居然去查了半天 compilefindall 函数……沃日,最后再重新一看那个源码:

<dd>
    <i class="board-index board-index-1">1</i>
    <a href="/films/1203" title="霸王别姬" class="image-link" data-act="boarditem-click" data-val="{movieId:1203}">
      <img src="//s3plus.meituan.net/v1/mss_e2821d7f0cfe4ac1bf9202ecf9590e67/cdn-prod/file:5788b470/image/loading_2.e3d934bf.png" alt="" class="poster-default">
      <img alt="霸王别姬" class="board-img" src="https://p0.meituan.net/movie/[email protected]_220h_1e_1c">
    </a>
    <div class="board-item-main">
      <div class="board-item-content">
              <div class="movie-item-info">
        <p class="name"><a href="/films/1203" title="霸王别姬" data-act="boarditem-click" data-val="{movieId:1203}">霸王别姬</a></p>
        <p class="star">
                主演:张国荣,张丰毅,巩俐
        </p>
<p class="releasetime">上映时间:1993-07-26</p>    </div>
    <div class="movie-item-number score-num">
<p class="score"><i class="integer">9.</i><i class="fraction">5</i></p>        
    </div>

      </div>
    </div>

</dd>

​ 我又吐了……人家的标签是嘛?是 <i>标签,我开始写的啥?是 <li> 标签……一开始就错了,能给你返回结果,骚年做梦去吧……一些简单的问题恰巧是一些人经常忽视的,有些你眼中的 Bug 可能就是哪个细节没做到位,而且不易察觉,因为大多数人会认为这么简单的东西没问题,恰巧这些忽视的就是问题所在。

​ 现在这个极为简单的插件算是基本完工,还有一些东西需要完善,比如多几个跟随图标的选择,字体这一块暂时是固定死的,用了字珠压缩字体包提高一下速度,后续也会像跟随图标一样可供选择,其文字和字体的选择后续会安排上……还有一个毛病就是弹出的字体是用的 <span> 标签,开始以为会对博客中的一些标签产生影响(我觉得id冲突了),可以通过创建新的标签 tag 进行解决(HTML5)刚才一看用的通配符选择器,(lll¬ω¬)我的我的~然后我看着本地的图标跟随很流畅如德芙巧克力般纵享丝滑然后博客里一启用咋感觉这么僵硬~~陷入沉思……

该看网课了,已经落下三天了,再不看看说不过去……这个等着以后再进行完善吧(●ˇ∀ˇ●)

git插件地址


召唤看板娘