WordPress 打造自己的代码高亮

代码高亮对于程序员写博客来说,还是非常有必要的,毕竟你写个文章贴个代码看起来乱七八糟,也不好看!

博客写了好多年了,贴的代码也不少,之前一直使用的插件,总感觉有点过重了,为了一个代码高亮引入了太多JS、CSS。

所以就打算自己打造一个,这个是基于 highlight.js 来打造的!其中使用了一个滚动条的美化JS jquery.mCustomScrollbar.min.js

引入需要文件

将文件引入主题的 functions.php

// functions.php
function register_scripts() {
	wp_register_script('highlight', get_template_directory_uri(). '/extend/highlight.min.js', array('jquery'), '9.12.0', true);
	wp_register_script('mousewheel', get_template_directory_uri(). '/extend/jquery.mousewheel.min.js', array('jquery'), '3.1.13', true);
	wp_register_script('mCustomScrollbar', get_template_directory_uri(). '/extend/jquery.mCustomScrollbar.min.js', array('jquery','mousewheel'), '3.1.5', true);
	wp_register_script('extend', get_template_directory_uri(). '/extend/custom.js', array('jquery','highlight'), '1.0', true);
}
add_action('init','register_scripts');

function register_styles() {
	wp_register_style('highlight', get_template_directory_uri(). '/extend/highlight.css', null, '9.12.0', 'all');
	wp_register_style('mCustomScrollbar', get_template_directory_uri(). '/extend/jquery.mCustomScrollbar.min.css', null, '3.1.5', 'all');
	wp_register_style('extend', get_template_directory_uri(). '/extend/custom.css', null, '1.0', 'all');
}
add_action('init',register_styles);

function load_scripts() {
	wp_enqueue_script('highlight');
	wp_enqueue_script('mousewheel');
	wp_enqueue_script('mCustomScrollbar');
	wp_enqueue_script('extend');
}
add_action( 'the_post', 'load_scripts');

function load_styles() {
	wp_enqueue_style('highlight');
	wp_enqueue_style('extend');
	wp_enqueue_style('mCustomScrollbar');
}
add_action( 'the_post', 'load_styles' );

注册按钮

// functions.php
add_action('admin_head', 'highlight_code_plugin');
function highlight_code_plugin() {

	global $typenow;

	// 判断用户是否有编辑文章和页面的权限
	if ( ! current_user_can('edit_posts') && ! current_user_can('edit_pages') ) {
		return;
	}

	if (! in_array($typenow, array('post','page'))) {
		return;
	}

	//判断用户是否使用可视化编辑器     
	if ( get_user_option('rich_editing') == 'true' ) {
		add_filter( 'mce_external_plugins', 'add_plugin' );
		add_filter( 'mce_buttons', 'register_button' );
	}
}

// 注册按钮
function register_button($buttons) {
	array_push($buttons, 'highlight_code');
	return $buttons;
}

// 注册TinyMCE按钮插件
function add_plugin($plugin_array) {
	$plugin_array['highlight_code'] = get_template_directory_uri() . '/extend/mce_code_plugin.js';
	return $plugin_array;
}

添加tinyMCE编辑按钮功能

// mce_code_plugin.js
(function($) {
	tinymce.PluginManager.add('highlight_code', function(editor, url) {
		editor.addButton('highlight_code', {
			// text: 'Code',
			// icon: false,
			title: 'Highlight Code',
			icon: 'wp_code',
			onclick: function() {
				// Examlpes: https://www.tinymce.com/docs/api/tinymce/tinymce.windowmanager/
				editor.windowManager.open({
					width: 780,
					height: 650,
					title: 'Insert Code',
					body: [{
						type: 'listbox',
						name: 'code_type',
						label: 'Code Type',
						'values': [{
							text: 'Java',
							value: 'java'
						}, {
							text: 'Python',
							value: 'python'
						}, {
							text: 'Bash',
							value: 'bash'
						}, {
							text: 'Shell',
							value: 'shell'
						}, {
							text: 'Php',
							value: 'php'
						}, {
							text: 'Sql',
							value: 'sql'
						}, {
							text: 'JavaScript',
							value: 'javascript'
						}, {
							text: 'Json',
							value: 'json'
						}, {
							text: 'Xml',
							value: 'xml'
						}, {
							text: 'Css',
							value: 'css'
						}, {
							text: 'Diff',
							value: 'diff'
						}]
					}, {
						type: 'textbox',
						name: 'body',
						multiline: true,
						minWidth: 650,
						minHeight: 580
						// label: 'Body'
					}],
					onsubmit: function(e) {
						// Insert content when the window form is submitted
						// Examlpes:
						// tinyMCE.editors[0].insertContent('asdasd')

						// https://www.tinymce.com/docs/api/tinymce.html/tinymce.html.entities/#encoderaw
						// tinymce.html.Entities.encodeRaw(e.data.body) 格式化html标签
						editor.insertContent('<pre class="' + e.data.code_type + '"><code>' + tinymce.html.Entities.encodeRaw(e.data.body) + '</code></pre>');
					}
				});
			}
		});

		return {
			getMetadata: function() {
				return {
					title: "Highlight Code plugin",
					url: "https://jalena.bcsytv.com"
				};
			}
		};

	})
})(jQuery);

添加hljs初始化

// custom.js
jQuery(document).ready(function($) {

	$('pre code').each(function(i, block) {
		hljs.highlightBlock(block);
	});

	$(".hljs").mCustomScrollbar({
		theme: "light-thin",
		axis: "x",
		autoHideScrollbar: true,
		mouseWheel: {
			axis: "y",
			enable: false
		}
	});
});

到此就完成了。附上一个图片最终的样子吧!

Windows 镜像启动盘制作

Rufus 是一个可以帮助格式化和创建可引导USB闪存盘的工具,比如 USB 随身碟,记忆棒等等。

在如下场景中会非常有用:

  • 你需要把一些可引导的ISO格式的镜像(Windows,Linux,UEFI等)创建成USB安装盘的时候
  • 你需要使用一个还没有安装操作系统的设备的时候
  • 你需要从DOS系统刷写BIOS或者其他固件的时候
  • 你需要运行一个非常底层的工具的时候

Rufus 麻雀虽小,五脏俱全,体积虽小,功能全面。

制作步骤

update from

在某些情况下,我们需要update数据,但数据来自其他表,通常我们是这样

UPDATE table1 alias
SET (column_name, column_name ) = (
SELECT (column_name, column_name)
FROM table2
WHERE column_name = alias.column_name)
WHERE column_name = VALUE;

但更新的列太多的话,那就非常麻烦。。

在MS SQL里面,我们可以这样

UPDATE FT_1_49E74BA98FF7886574E1
SET
  FN01 = v.su00, -- FN01、姓名
  FN02 = v.su36, -- FN02、部门
  FN03 = v.su34, -- FN03、岗位
  FN04 = v.su21 --FN04、入职时间
FROM FE_BASE5..GROUP_USER_V AS v
WHERE FN09 = v.su01
      AND FN09 = 'AC0001';

Oracle 和 DB2 可以这样

UPDATE A SET (A1, A2, A3) = (SELECT B1, B2, B3 FROM B WHERE A.ID = B.ID)

Odoo 引入CSS及JavaScript

在module/view下创建一个新的XML

<?xml version="1.0" encoding="utf-8"?>
<odoo>
        <template id="assets_backend" name="web_kanban assets" inherit_id="web.assets_backend">
            <xpath expr="//script[last()]" position="inside">
                <link rel="stylesheet" href="/web_kanban/static/src/less/kanban_dashboard.less"/>
                <link rel="stylesheet" href="/web_kanban/static/src/less/kanban_view.less"/>

                <script type="text/javascript" src="/web_kanban/static/src/js/kanban_record.js"></script>
                <script type="text/javascript" src="/web_kanban/static/src/js/kanban_relational.js"></script>
                <script type="text/javascript" src="/web_kanban/static/src/js/kanban_quick_create.js"></script>
                <script type="text/javascript" src="/web_kanban/static/src/js/kanban_column.js"></script>
                <script type="text/javascript" src="/web_kanban/static/src/js/kanban_view.js"></script>
                <script type="text/javascript" src="/web_kanban/static/src/js/kanban_widgets.js"></script>
                <script type="text/javascript" src="/web_kanban/static/src/js/compatibility.js"></script>
            </xpath>
        </template>
</odoo>

引入XML至__manifest__.py文件

{
    'data':['views/resources.xml']
}

方法二

直接在__manifest__.py引入

'css': ['static/src/css/sale.css'],

Odoo 常用技巧

View

隐藏Field

<field name="currency_id" invisible="True"/>
<field name="currency_id" invisible="1"/>

在某种条件下隐藏

<field name="expense_description" attrs="{'invisible':[('expense_audit','!=','1')]}" />

隐藏label

<field name="description" widget="html" nolabel="True"/>
<field name="description" widget="html" nolabel="1"/>

只读 readonly

<field name="budget_id" readonly="True"/>

条件 domain

<field name="product_id" domain="[('pro_type','=','rests')]"/>

设定值 eval

<field name="fill_date" eval="datetime.now()" readonly="True"/>

表单传值 context (default_ 开始代表直接赋值过去)

<button class="oe_stat_button" name="%(budget_review_action)d" type="action" icon="fa-calendar-check-o" attrs="{'invisible':[('state','!=','check')]}" context="{'default_budget_id': id, 'default_contract_area': square, 'default_contract_price': total_price, 'default_start_date': start_date, 'default_end_date': end_date}" string="创建审核单"/>a

Widget

many2one widget (default)

  •  no_quick_create - remove the Create and edit... option.
  •  no_create_edit - remove the Create "search_value" option.
  •  no_create - no_quick_create and no_create_edit combined.
  •  no_open - in read mode: do not render as a link.
<field name="field_name" options="{'no_quick_create': True, 'no_create_edit' : True}"/>

many2many widget (default)

  • no_create - remove the Create button.
<field name="field_name" options="{'no_create': True}"/>

many2many_tags widget

  • no_quick_create - remove the Create and edit... option.
  • no_create_edit - remove the Create "search_value" option.
  • no_create - no_quick_create and no_create_edit together.
<field name="field_name" widget="many2many_tags" options="{'no_create_edit': True}"/>

one2many tree

  • create - remove the Create button.
  • edit - remove the Edit button.
  • delete - remove the Delete button.
<field name="basic_incidentals" mode="tree" nolabel="1">
   <tree create="false" edit="false" delete="false">
      <field name="name"/>
      <field name="model"/>
      <field name="specifications"/>
      <field name="price" invisible="True"/>
      <field name="number" invisible="True"/>
      <field name="unit" invisible="True"/>
      <field name="total_price" invisible="True"/>
      <field name="remarks" invisible="True"/>
   </tree>
</field>

Fields

生成一个动态的Selection,比如当前时间的前后5年!

import datetime
year = fields.Selection(string=u'年度', selection=[(num, str(num)) for num in range((datetime.datetime.now().year - 5), (datetime.datetime.now().year + 5))])

Odoo Environment(env)

Environment

environment是Odoo中操作DB的总句柄,可以通过下面几种方式获得:

对于继承了Model的类来说可以通过如下方式

self.env['modelname']

在请求Controller可以通过

request.env()

通过模型类或者模型对象获取

cls.env
product.env

一些常用上下文参数

# 当前用户
self.env.user
# 当前用户id
self.env.uid
#当前语言代码
self.env.lang
#当前数据库连接
self.env.cr

使用例子

# 利用 env[model] 获取模型类对象
self.env['ir.model'].search([('state', '!=', 'manual')])
# 利用 env.cr 执行sql语句
self.env.cr.execute(query, (value,))