PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.4.1
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.4.1
2.4.0 2.4.1 2.3.8 2.3.7 2.3.6 2.3.5 2.3.4 2.3.3 2.3.2 2.3.1 2.2.0 2.1.21 2.1.20 2.1.19 2.1.18 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.16 2.1.2 All 57 releases
← All changes | includes/Admin/AdminAssets.php +104 -12 2.2.02.4.1 View file →
@@ -48,15 +48,58 @@
48 48 * Enqueue stylesheets
49 49 */
50 50 private function enqueueStyles() {
51 51
52 + // Tailwind: the purged ~47 KB build is the default; the full 2.8 MB
53 + // dump stays on disk as the fallback.
54 + //
55 + // The purged file is the shipped v2 bundle with unused rules removed --
56 + // NOT a v3 rebuild, which would rename utilities and change the palette.
57 + // Every rule it keeps is byte-identical to the full file, so anything
58 + // still on a page renders exactly as before. It was verified by
59 + // pixel-diffing 41 admin screens (every core page, every addon page,
60 + // three breakpoints, the drawer, a modal and toasts) against the full
61 + // file: zero differing pixels. See tools/tailwind-build/README.md.
62 + //
63 + // A site that adds markup using utilities the plugin never uses --
64 + // a custom template, a child theme -- can go back to the full file:
65 + // update_option('easy_invoice_tailwind_purged', '0');
66 + // or
67 + // add_filter('easy_invoice_use_purged_tailwind', '__return_false');
68 + //
69 + // The option was previously opt-IN ('1' enabled the purged file). It is
70 + // now opt-OUT: only an explicit '0' disables it. A site that had set
71 + // '1' keeps working; a site that never set it gets the win.
72 + //
73 + // The file_exists check below means a deployment that lost the purged
74 + // file falls back to the full one rather than 404-ing the stylesheet.
75 + $purged_option = get_option('easy_invoice_tailwind_purged', '1');
76 + $use_purged = apply_filters(
77 + 'easy_invoice_use_purged_tailwind',
78 + '0' !== (string) $purged_option && false !== $purged_option
79 + );
80 + $purged_rel = 'assets/lib/tailwind/tailwind.purged.min.css';
81 + $shipped_rel = 'assets/lib/tailwind/tailwind.min.css';
82 + $tailwind_rel = ($use_purged && file_exists(EASY_INVOICE_PLUGIN_DIR . $purged_rel))
83 + ? $purged_rel
84 + : $shipped_rel;
85 +
52 86 wp_enqueue_style(
53 87 'easy-invoice-tailwind',
54 - EASY_INVOICE_PLUGIN_URL . 'assets/lib/tailwind/tailwind.min.css',
88 + EASY_INVOICE_PLUGIN_URL . $tailwind_rel,
55 89 array(),
56 90 EASY_INVOICE_VERSION
57 91 );
58 92
93 + // Colour names the views use that Tailwind v2 never had (amber, emerald,
94 + // teal …) — without these every amber notice and emerald badge was unstyled.
95 + wp_enqueue_style(
96 + 'easy-invoice-palette-ext',
97 + EASY_INVOICE_PLUGIN_URL . 'assets/css/palette-ext.css',
98 + array( 'easy-invoice-tailwind' ),
99 + EASY_INVOICE_VERSION
100 + );
101 +
59 102 $page = isset($_GET['page']) ? sanitize_text_field($_GET['page']) : '';
60 103
61 104 // Main plugin layout + header strip alignment (always on Easy Invoice admin screens).
62 105 wp_enqueue_style(
@@ -76,18 +119,47 @@
76 119 EASY_INVOICE_VERSION
77 120 );
78 121 }
79 122
80 - wp_enqueue_style(
81 - 'font-awesome',
82 - EASY_INVOICE_PLUGIN_URL . 'assets/lib/font-awesome/css/all.min.css',
83 - array(),
84 - EASY_INVOICE_VERSION
85 - );
123 + // Font Awesome (~87 KB) is used by the heavyweight templates
124 + // (clients, settings, reports, invoices, quotes, payments) but
125 + // NOT by the lightweight admin pages — Dashboard, Addons grid,
126 + // License, Free-vs-Pro, Join Community, and every addon-settings
127 + // sub-page (those use dashicons). Skip enqueueing FA on the
128 + // deny-listed pages to save the bandwidth and the parse cost.
129 + // Filterable so site-specific custom templates can opt back in.
130 + $fa_deny = (array) apply_filters('easy_invoice_font_awesome_skip_pages', [
131 + 'easy-invoice-dashboard',
132 + 'easy-invoice-addons',
133 + 'easy-invoice-license',
134 + 'easy-invoice-free-vs-pro',
135 + 'easy-invoice-join-community',
136 + ]);
137 + $is_addon_subpage = ($page !== '' && strpos($page, 'easy-invoice-addon-') === 0);
138 + if (!in_array($page, $fa_deny, true) && !$is_addon_subpage) {
139 + wp_enqueue_style(
140 + 'font-awesome',
141 + EASY_INVOICE_PLUGIN_URL . 'assets/lib/font-awesome/css/all.min.css',
142 + array(),
143 + EASY_INVOICE_VERSION
144 + );
145 + }
86 146
87 147
88 - // Add RTL support
89 - wp_style_add_data('easy-invoice-admin', 'rtl', 'replace');
148 + // RTL support.
149 + //
150 + // Strategy: 'append' (not 'replace') because Tailwind utility
151 + // classes generated into easy-invoice.css remain valid LTR — only
152 + // the small set of custom directional rules (sidebar borders,
153 + // page-header negative margins, drawer offsets) need mirroring.
154 + // WordPress loads assets/css/easy-invoice-rtl.css AFTER
155 + // easy-invoice.css when is_rtl() is true; that file holds only the
156 + // directional overrides.
157 + //
158 + // 'easy-invoice-main' is the handle of the file we want to extend
159 + // (line 87 above). The previous handle 'easy-invoice-admin' did
160 + // not exist and so the call was a no-op.
161 + wp_style_add_data('easy-invoice-main', 'rtl', 'append');
90 162 }
91 163
92 164 /**
93 165 * Enqueue scripts
@@ -113,12 +185,27 @@
113 185 wp_enqueue_script('wp-hooks');
114 186
115 187 // Settings page script
116 188 if (isset($_GET['page']) && $_GET['page'] === 'easy-invoice-settings') {
189 + // settings.js calls .sortable() and .disableSelection() on the
190 + // payment-gateway list, so jQuery UI Sortable must be present and
191 + // printed first. SettingsController::enqueueAdminScripts() also
192 + // registers this same handle; WordPress keeps whichever call runs
193 + // first and silently drops the other's dependency array, and this
194 + // one runs first (AdminAssets is wired up during EasyInvoice::init,
195 + // before SettingsController::init). Declaring the jQuery UI handles
196 + // here lets wp_scripts resolve the order rather than leaving it to
197 + // the sequence the two enqueue callbacks happen to fire in.
198 + //
199 + // Only core handles are listed. select2 / easy-invoice-toast are
200 + // also used by settings.js but are registered by SettingsController
201 + // later in the request; naming them here would mean settings.js is
202 + // dropped entirely if that callback ever stops running, so they are
203 + // deliberately left out.
117 204 wp_enqueue_script(
118 205 'easy-invoice-settings',
119 206 EASY_INVOICE_PLUGIN_URL . 'assets/js/settings.js',
120 - array('jquery', 'wp-util', 'wp-api-fetch', 'wp-i18n'),
207 + array('jquery', 'jquery-ui-core', 'jquery-ui-sortable', 'wp-util', 'wp-api-fetch', 'wp-i18n'),
121 208 EASY_INVOICE_VERSION,
122 209 true
123 210 );
124 211
@@ -197,10 +284,15 @@
197 284 ));
198 285 wp_enqueue_script('easy-invoice-bulk-send-email-teaser');
199 286 }
200 287
201 - // jsPDF for PDF generation - available on all Easy Invoice pages
202 - wp_register_script('jspdf', 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js', array(), '2.5.1', true);
288 + // jsPDF + html2canvas for PDF generation - available on all Easy Invoice pages.
289 + // Both are bundled in assets/js/vendors/ rather than loaded from a CDN:
290 + // WordPress.org requires every asset to ship inside the plugin, and a remote
291 + // CDN is a hard runtime dependency for a core feature.
292 + wp_register_script('html2canvas', EASY_INVOICE_PLUGIN_URL . 'assets/js/vendors/html2canvas.min.js', array(), '1.4.1', true);
293 + wp_register_script('jspdf', EASY_INVOICE_PLUGIN_URL . 'assets/js/vendors/jspdf.umd.min.js', array(), '2.5.1', true);
294 + wp_enqueue_script('html2canvas');
203 295 wp_enqueue_script('jspdf');
204 296
205 297
206 298 // Conditionally load invoice-specific scripts only on invoice pages