-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinit.php
137 lines (124 loc) · 4.47 KB
/
init.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<?php
/**
* Plugin Name: Shortcode for Vue.js
* Description: Injection of Vue.js based application via shortcode.
* Version: 1.0
* Author: Patrick Lai
* @copyright Copyright (c) 2019,2020 Patrick Lai
*/
//--------------------------------------------------------------
/**
* Shortcode [pl2010_vue] for Vue.js integration.
*
* Attributes:
* app - Name for the Vue.js integration app (required).
*
* Other attributes are treated as parameters for the integration app.
*
* The 'app' attribute refers to the same named directory under the 'apps'
* directory of this plugin. Two files are expected there, namely index.html
* and index.js. For example, [pl2010_vue app="demo_01"/] corresponds to
* '.../apps/demo_01/index.html' and '.../apps/demo_01/index.js'.
*
* The index.html contains HTML to be wrapped by the <div> mount point
* of the Vue.js application. For the 'demo_01' app, this shortcode would
* return something like this:
*
* <div class="pl2010_vue pl2010_vue_app_demo_01">
* ...
* content from .../apps/demo_01/index.html
* ...
* </div>
*
* The shortcode also enqueues the 'index.js' script file, which should
* assign an initialization function to the variable pl2010_vue_init_<app>,
* (pl2010_vue_init_demo_01 in our example). The shortcode generates
* Javascript code to call this function with an object with these
* properties:
*
* app - Application name, i.e. the 'app' attribute given to the shortcode.
* params - Parameters for the Vue.js application.
* el - The 'el' property for Vue object.
* siteurl - WordPress site URL.
* locale - Current locale (c.f. {@link get_locale()}).
*
* The function may assume the availability of jQuery, Vue, and
* wpApiSettings.
*/
add_shortcode('pl2010_vue', function($attrs, $content=null, $tag='pl2010_vue') {
$HERE = plugin_dir_path(__FILE__);
$BASE = plugin_dir_url(__FILE__);
// Enqueue dependent Vue.js etc.
// Note that 'wp-api' is enqueued because Vue.js application typically
// makes API call.
// TODO: configurable?
wp_enqueue_script('wp-api');
wp_enqueue_script('jquery');
wp_enqueue_script('vue', "{$BASE}js/vue-2.6.11.min.js", [], null);
// Classes for error messages.
$errorClasses = 'error pl2010_vue_error';
// App name is required. It must be like a Javascript identifier.
$app = empty($attrs['app']) ? '' : $attrs['app'];
if ($app == '') {
return "<div class=\"$errorClasses\">"
. "Missing 'app' attribute in shortcode '$tag'."
. '</div>';
}
if (!preg_match('%^[[:alpha:]][_[:alpha:][:digit:]]*$%', $app)) {
return "<div class=\"$errorClasses\">"
. "Invalid 'app' attribute in shortcode '$tag'."
. '</div>';
}
// Classes for Vue.js <div> mount point.
$mntPtClasses = "pl2010_vue pl2010_vue_app_{$app}";
// Allocate a sequence # for building ID for the Vue.js <div> mount point.
static $LAST_SEQ;
++$LAST_SEQ;
// Parameters are provided as shortcode attributes. Separate
// generic attributes from parameters.
$params = $attrs;
$attrs = array_map('trim', shortcode_atts([
'app' => $app,
], $attrs, $tag));
$params = array_diff_key($params, $attrs);
// Prepare context for Vue initialization.
$vue_ctx = [
'app' => $app,
'params' => $params,
'el' => "pl2010_vue_{$LAST_SEQ}",
'siteurl' => get_option('siteurl', ''),
'locale' => get_locale(),
];
// Use an empty script as an anchor for in-line addition.
// The dependency (on jquery etc.) is for the init JS script as well.
$initAnchor = "pl2010_vue_init";
wp_enqueue_script($initAnchor, "{$BASE}js/empty.js", [
'jquery',
'vue',
'wp-api',
], null);
// Enqueue init JS, using file mtime as version.
$initPath = "apps/{$app}/index.js";
$initName = $initFVar = "pl2010_vue_init_{$app}";
wp_enqueue_script($initName, $BASE.$initPath, [
$initAnchor,
], filemtime($HERE.$initPath));
// Add JS to call init function, which has access to a local
// 'vue_ctx' variable that mirrors the PHP $vue_ctx.
$jsVueCtx = json_encode($vue_ctx);
$inlineJs = <<<EOS
var $initFVar;
jQuery(document).ready(function() {
const init = window.$initFVar || $initFVar;
if (init) {
init($jsVueCtx);
}
});
EOS;
wp_add_inline_script($initAnchor, $inlineJs);
// Load HTML fragment and render the Vue.js application <div>.
$html = file_get_contents("{$HERE}/apps/{$app}/index.html");
return "<div id=\"{$vue_ctx['el']}\" class=\"{$mntPtClasses}\">$html</div>";
});
//--------------------------------------------------------------
// vim: set ts=4 noexpandtab fdm=marker syntax=php: ('zR' to unfold all)