{"id":37956,"date":"2026-03-18T20:16:27","date_gmt":"2026-03-18T13:16:27","guid":{"rendered":"https:\/\/dps.media\/?p=37956"},"modified":"2026-03-18T20:25:33","modified_gmt":"2026-03-18T13:25:33","slug":"wordpress-plugin-dev-guide","status":"publish","type":"post","link":"http:\/\/dps.media\/zh\/wordpress-plugin-dev-guide\/","title":{"rendered":"WordPress \u63d2\u4ef6\u5f00\u53d1\u6307\u5357"},"content":{"rendered":"<?xml encoding=\"utf-8\" ?><style>\n@import url('https:\/\/fonts.googleapis.com\/css2?family=Syne:wght@600;700;800&family=JetBrains+Mono:wght@300;400;500&family=DM+Sans:wght@300;400;500&display=swap');\n\n#dps-guide {\n  --bg:      #09090e;\n  --bg2:     #0e0e18;\n  --faint:   #1a1a2c;\n  --border:  rgba(255,255,255,0.07);\n  --border2: rgba(255,255,255,0.13);\n  --text:    #ddddf0;\n  --muted:   #6060a0;\n  --blue:    #5b9cf6;\n  --green:   #34d399;\n  --purple:  #a78bfa;\n  --amber:   #fbbf24;\n  --slate:   #94a3b8;\n  --coral:   #fb7185;\n  --blue-bg:   rgba(91,156,246,0.08);\n  --green-bg:  rgba(52,211,153,0.08);\n  --purple-bg: rgba(167,139,250,0.08);\n  --amber-bg:  rgba(251,191,36,0.08);\n  --slate-bg:  rgba(148,163,184,0.08);\n  --coral-bg:  rgba(251,113,133,0.08);\n  background: var(--bg);\n  color: var(--text);\n  font-family: 'DM Sans', sans-serif;\n  line-height: 1.6;\n  border-radius: 16px;\n  overflow: hidden;\n  position: relative;\n}\n\n#dps-guide *,#dps-guide *::before,#dps-guide *::after{box-sizing:border-box;margin:0;padding:0;}\n\n\/* TOP BAR *\/\n#dps-guide .dps-topbar{background:rgba(9,9,14,0.92);backdrop-filter:blur(20px);border-bottom:1px solid var(--border);padding:0 40px;height:52px;display:flex;align-items:center;justify-content:space-between;position:sticky;top:0;z-index:50;}\n#dps-guide .dps-brand{display:flex;align-items:center;gap:10px;text-decoration:none;}\n#dps-guide .dps-logo{width:28px;height:28px;border-radius:7px;background:linear-gradient(135deg,rgba(91,156,246,.35),rgba(167,139,250,.35));border:1px solid rgba(167,139,250,.25);display:flex;align-items:center;justify-content:center;font-family:'Syne',sans-serif;font-size:13px;font-weight:800;color:#c4b5f4;flex-shrink:0;}\n#dps-guide .dps-brand-name{font-family:'Syne',sans-serif;font-size:14px;font-weight:700;color:#fff;letter-spacing:-.01em;}\n#dps-guide .dps-topbar-right{display:flex;align-items:center;gap:14px;}\n#dps-guide .dps-nav-tag{font-family:'JetBrains Mono',monospace;font-size:10px;color:var(--muted);letter-spacing:.04em;}\n#dps-guide #dps-copy-btn{display:flex;align-items:center;gap:7px;background:var(--faint);border:1px solid var(--border2);border-radius:8px;padding:6px 14px;cursor:pointer;font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--text);transition:all .18s;white-space:nowrap;}\n#dps-guide #dps-copy-btn:hover{background:rgba(255,255,255,0.06);border-color:rgba(255,255,255,0.2);}\n#dps-guide #dps-copy-btn.copied{background:rgba(52,211,153,0.08);border-color:rgba(52,211,153,.35);color:var(--green);}\n\n\/* PAGE *\/\n#dps-guide .dps-page{padding:48px 40px 64px;max-width:1080px;margin:0 auto;}\n\n\/* HEADER *\/\n#dps-guide .author-pill{display:inline-flex;align-items:center;gap:10px;background:var(--faint);border:1px solid var(--border2);border-radius:99px;padding:6px 14px 6px 8px;margin-bottom:28px;}\n#dps-guide .author-av{width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,rgba(91,156,246,.4),rgba(167,139,250,.4));display:flex;align-items:center;justify-content:center;font-family:'Syne',sans-serif;font-size:12px;font-weight:800;color:#fff;}\n#dps-guide .author-pill span{font-size:13px;color:var(--text);font-weight:500;}\n#dps-guide .author-pill em{font-style:normal;color:var(--muted);font-size:12px;}\n#dps-guide h1{font-family:'Syne',sans-serif;font-size:clamp(34px,5vw,58px);font-weight:800;line-height:.95;letter-spacing:-.03em;color:#fff;margin-bottom:16px;}\n#dps-guide h1 span{background:linear-gradient(120deg,var(--blue) 0%,var(--purple) 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;}\n#dps-guide .header-sub{font-size:15px;font-weight:300;color:var(--muted);max-width:500px;margin-bottom:56px;}\n\n\/* SECTION LABEL *\/\n#dps-guide .slabel{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.15em;text-transform:uppercase;color:var(--muted);display:flex;align-items:center;gap:10px;margin-bottom:20px;}\n#dps-guide .slabel::after{content:'';flex:1;height:1px;background:var(--border);}\n\n\/* TAGS *\/\n#dps-guide .tag{font-family:'JetBrains Mono',monospace;font-size:10px;font-weight:500;padding:3px 10px;border-radius:4px;border:1px solid;display:inline-flex;align-items:center;gap:6px;white-space:nowrap;}\n#dps-guide .tag .dot{width:5px;height:5px;border-radius:50%;background:currentColor;}\n#dps-guide .t-blue  {color:var(--blue);  background:var(--blue-bg);  border-color:rgba(91,156,246,.25);}\n#dps-guide .t-green {color:var(--green); background:var(--green-bg); border-color:rgba(52,211,153,.25);}\n#dps-guide .t-purple{color:var(--purple);background:var(--purple-bg);border-color:rgba(167,139,250,.25);}\n#dps-guide .t-amber {color:var(--amber); background:var(--amber-bg); border-color:rgba(251,191,36,.25);}\n#dps-guide .t-slate {color:var(--slate); background:var(--slate-bg); border-color:rgba(148,163,184,.25);}\n#dps-guide .t-coral {color:var(--coral); background:var(--coral-bg); border-color:rgba(251,113,133,.25);}\n\n\/* CARD *\/\n#dps-guide .card{background:var(--bg2);border:1px solid var(--border);border-radius:16px;overflow:hidden;}\n#dps-guide .card-pad{padding:28px;}\n\n\/* FILE TREE *\/\n#dps-guide .tree-section{margin-bottom:56px;}\n#dps-guide .tree-wrap{background:var(--bg2);border:1px solid var(--border);border-radius:16px;overflow:hidden;}\n#dps-guide .tree-topbar-inner{background:var(--faint);border-bottom:1px solid var(--border);padding:10px 20px;display:flex;align-items:center;gap:8px;}\n#dps-guide .tree-topbar-inner span{width:10px;height:10px;border-radius:50%;}\n#dps-guide .tree-topbar-inner small{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--muted);margin-left:8px;}\n#dps-guide .tree-body{display:grid;grid-template-columns:1fr 1fr;gap:0;}\n#dps-guide .tree-col{padding:24px 28px;}\n#dps-guide .tree-col+.tree-col{border-left:1px solid var(--border);}\n#dps-guide .tree-label{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);margin-bottom:14px;}\n#dps-guide .tree{font-family:'JetBrains Mono',monospace;font-size:12px;line-height:2.1;}\n#dps-guide .tree .d{color:var(--blue);font-weight:500;}\n#dps-guide .tree .f{color:var(--text);}\n#dps-guide .tree .x{color:var(--green);font-weight:500;}\n#dps-guide .tree .c{color:var(--muted);font-size:11px;}\n#dps-guide .tree .i{color:var(--coral);}\n#dps-guide .tree .indent{padding-left:20px;}\n#dps-guide .tree .indent2{padding-left:40px;}\n#dps-guide .tree .indent3{padding-left:60px;}\n\n\/* FLOW *\/\n#dps-guide .flow-section{margin-bottom:56px;}\n#dps-guide .flow-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;}\n#dps-guide .fcard{background:var(--bg2);border:1px solid var(--border);border-radius:16px;overflow:hidden;}\n#dps-guide .fcard-head{padding:20px 24px 0;}\n#dps-guide .fcard h3{font-family:'Syne',sans-serif;font-size:18px;font-weight:700;color:#fff;letter-spacing:-.01em;margin-bottom:4px;margin-top:10px;}\n#dps-guide .fcard-sub{font-size:12.5px;color:var(--muted);font-weight:300;margin-bottom:20px;}\n#dps-guide .fcard-body{padding:0 24px 24px;}\n#dps-guide .steps{display:flex;flex-direction:column;}\n#dps-guide .step{display:flex;gap:14px;align-items:flex-start;}\n#dps-guide .step-l{display:flex;flex-direction:column;align-items:center;flex-shrink:0;}\n#dps-guide .step-dot{width:28px;height:28px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-family:'JetBrains Mono',monospace;font-size:11px;font-weight:500;border:1px solid;flex-shrink:0;}\n#dps-guide .step-line{width:1px;flex:1;min-height:14px;background:var(--border);margin:3px 0;}\n#dps-guide .step-r{padding-top:4px;padding-bottom:18px;}\n#dps-guide .step-title{font-size:13px;font-weight:500;color:var(--text);margin-bottom:2px;}\n#dps-guide .step-desc{font-size:12px;color:var(--muted);font-weight:300;line-height:1.55;}\n#dps-guide .code{margin-top:6px;background:var(--faint);border-radius:6px;padding:7px 12px;font-family:'JetBrains Mono',monospace;font-size:11px;line-height:1.9;}\n#dps-guide .code .cmd{color:var(--green);}\n#dps-guide .code .cmt{color:var(--muted);}\n#dps-guide .code .val{color:var(--amber);}\n#dps-guide .code .key{color:var(--blue);}\n\n\/* SCRIPTS *\/\n#dps-guide .scripts-section{margin-bottom:56px;}\n#dps-guide .scripts-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;}\n#dps-guide .scmd{background:var(--bg2);border:1px solid var(--border);border-radius:12px;padding:18px 20px;transition:border-color .2s;}\n#dps-guide .scmd:hover{border-color:var(--border2);}\n#dps-guide .scmd-cmd{font-family:'JetBrains Mono',monospace;font-size:13px;font-weight:500;color:var(--green);margin-bottom:6px;}\n#dps-guide .scmd-what{font-size:12.5px;color:var(--muted);font-weight:300;line-height:1.5;margin-bottom:8px;}\n#dps-guide .scmd-detail{font-family:'JetBrains Mono',monospace;font-size:10px;color:var(--muted);border-top:1px solid var(--border);padding-top:8px;line-height:1.7;}\n\n\/* DO\/DONT *\/\n#dps-guide .dodonts{display:grid;grid-template-columns:1fr 1fr;gap:2px;border-radius:12px;overflow:hidden;border:1px solid var(--border);}\n#dps-guide .do-col{background:rgba(52,211,153,.04);padding:20px 22px;}\n#dps-guide .dont-col{background:rgba(251,113,133,.04);padding:20px 22px;}\n#dps-guide .do-head{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--green);margin-bottom:12px;display:flex;align-items:center;gap:8px;}\n#dps-guide .dont-head{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--coral);margin-bottom:12px;display:flex;align-items:center;gap:8px;}\n#dps-guide .do-head::before{content:'\u2713';font-size:12px;}\n#dps-guide .dont-head::before{content:'\u2717';font-size:12px;}\n#dps-guide .do-item,#dps-guide .dont-item{font-family:'JetBrains Mono',monospace;font-size:11.5px;padding:6px 10px;border-radius:6px;margin-bottom:4px;line-height:1.5;}\n#dps-guide .do-item{color:var(--green);background:rgba(52,211,153,.06);}\n#dps-guide .dont-item{color:var(--coral);background:rgba(251,113,133,.06);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.4);}\n\n\/* ZIP *\/\n#dps-guide .zip-section{margin-bottom:56px;}\n#dps-guide .zip-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;}\n#dps-guide .zip-card{background:var(--bg2);border:1px solid var(--border);border-radius:14px;overflow:hidden;}\n#dps-guide .zip-head{padding:14px 18px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:10px;}\n#dps-guide .zip-body{padding:14px 18px;}\n#dps-guide .zip-row{display:flex;align-items:center;justify-content:space-between;padding:7px 0;border-bottom:1px solid var(--border);}\n#dps-guide .zip-row:last-child{border-bottom:none;}\n#dps-guide .zip-path{font-family:'JetBrains Mono',monospace;font-size:11.5px;}\n#dps-guide .zip-note{font-size:11px;color:var(--muted);font-weight:300;}\n\n\/* ACCEPTANCE *\/\n#dps-guide .ac-section{margin-bottom:56px;}\n#dps-guide .ac-list{display:flex;flex-direction:column;gap:6px;}\n#dps-guide .ac-item{display:flex;align-items:center;gap:14px;background:var(--bg2);border:1px solid var(--border);border-radius:10px;padding:12px 18px;transition:border-color .2s;}\n#dps-guide .ac-item:hover{border-color:var(--border2);}\n#dps-guide .ac-check{width:20px;height:20px;border-radius:6px;border:1px solid rgba(52,211,153,.3);background:rgba(52,211,153,.06);display:flex;align-items:center;justify-content:center;font-size:11px;color:var(--green);flex-shrink:0;}\n#dps-guide .ac-text{font-size:13px;color:var(--text);font-weight:400;}\n\n\/* BOTTOM BAR *\/\n#dps-guide .dps-footer{border-top:1px solid var(--border);padding:22px 40px;display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:12px;}\n#dps-guide .dps-footer-l{display:flex;align-items:center;gap:10px;}\n#dps-guide .dps-footer p{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--muted);}\n#dps-guide .dps-footer-links{display:flex;gap:20px;}\n#dps-guide .dps-footer-links a{font-family:'JetBrains Mono',monospace;font-size:10px;color:var(--muted);text-decoration:none;}\n#dps-guide .dps-footer-links a:hover{color:var(--text);}\n\n\/* FADE *\/\n#dps-guide .fi{opacity:0;transform:translateY(18px);transition:opacity .5s ease,transform .5s ease;}\n#dps-guide .fi.in{opacity:1;transform:none;}\n\n@media(max-width:720px){\n  #dps-guide .dps-topbar{padding:0 20px;}\n  #dps-guide .dps-nav-tag{display:none;}\n  #dps-guide .dps-page{padding:32px 20px 48px;}\n  #dps-guide .tree-body,#dps-guide .flow-grid,#dps-guide .scripts-grid,#dps-guide .zip-grid,#dps-guide .dodonts{grid-template-columns:1fr;}\n  #dps-guide .tree-col+.tree-col{border-left:none;border-top:1px solid var(--border);}\n  #dps-guide .dps-footer{padding:20px;}\n}\n<\/style><div id=\"dps-guide\">\n\n  <!-- TOP BAR -->\n  <div class=\"dps-topbar\">\n    <div class=\"dps-brand\">\n      <div class=\"dps-logo\">D<\/div>\n      <span class=\"dps-brand-name\">DPS.MEDIA<\/span>\n    <\/div>\n    <div class=\"dps-topbar-right\">\n      <span class=\"dps-nav-tag\">WP \u63d2\u4ef6\u5f00\u53d1\u6307\u5357 \u2014 \u5185\u90e8<\/span>\n      <button id=\"dps-copy-btn\">\n        <svg width=\"13\" height=\"13\" viewbox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"5\" y=\"5\" width=\"9\" height=\"9\" rx=\"2\"><\/rect><path d=\"M11 5V3a2 2 0 0 0-2-2H3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2\"><\/path><\/svg>\n        <span id=\"dps-copy-label\">\u590d\u5236 Agent \u63d0\u793a\u8bcd<\/span>\n      <\/button>\n    <\/div>\n  <\/div>\n\n  <div class=\"dps-page\">\n\n    <!-- HEADER -->\n    <div class=\"fi\">\n      <div class=\"author-pill\">\n        <div class=\"author-av\">H<\/div>\n        <span>Hien<\/span>\n        <em>CEO \u00b7 DPS.MEDIA<\/em>\n      <\/div>\n      <h1>WordPress<br><span>\u63d2\u4ef6\u5f00\u53d1<\/span><br>\u6307\u5357<\/h1>\n      <p class=\"header-sub\">\u56e2\u961f\u7684 source \u2192 build \u2192 release \u6d41\u7a0b\u3002\u8db3\u4ee5\u652f\u6301\u672c\u5730\u5f00\u53d1\u3001\u6253\u5305 ZIP\u3001\u5b89\u88c5\u5230 WordPress \u751f\u4ea7\u73af\u5883\u3002.<\/p>\n    <\/div>\n\n    <!-- STACK PILLS -->\n    <div class=\"fi\" style=\"display:flex;gap:8px;flex-wrap:wrap;margin-bottom:56px;\">\n      <span class=\"tag t-blue\"><span class=\"dot\"><\/span>PHP 8.x<\/span>\n      <span class=\"tag t-blue\"><span class=\"dot\"><\/span>WordPress hooks API<\/span>\n      <span class=\"tag t-green\"><span class=\"dot\"><\/span>@wordpress\/scripts<\/span>\n      <span class=\"tag t-green\"><span class=\"dot\"><\/span>React (\u7ba1\u7406\u540e\u53f0 UI)<\/span>\n      <span class=\"tag t-green\"><span class=\"dot\"><\/span>Webpack 5<\/span>\n      <span class=\"tag t-amber\"><span class=\"dot\"><\/span>npm \u811a\u672c<\/span>\n      <span class=\"tag t-slate\"><span class=\"dot\"><\/span>Node.js \u2265 18<\/span>\n      <span class=\"tag t-slate\"><span class=\"dot\"><\/span>ZIP \u53d1\u5e03\u5305<\/span>\n    <\/div>\n\n    <!-- FILE TREE -->\n    <div class=\"tree-section fi\">\n      <div class=\"slabel\">\u76ee\u5f55\u7ed3\u6784<\/div>\n      <div class=\"tree-wrap\">\n        <div class=\"tree-topbar-inner\">\n          <span style=\"background:#ff5f57;\"><\/span>\n          <span style=\"background:#febc2e;\"><\/span>\n          <span style=\"background:#28c840;\"><\/span>\n          <small>my-plugin\/ \u2014 \u9879\u76ee\u6839\u76ee\u5f55<\/small>\n        <\/div>\n        <div class=\"tree-body\">\n          <div class=\"tree-col\">\n            <div class=\"tree-label\">\u6e90\u7801 (\u5f00\u53d1)<\/div>\n            <div class=\"tree\">\n              <div><span class=\"d\">my-plugin.php<\/span> <span class=\"c\">\u2190 \u4e3b\u63d2\u4ef6\u6587\u4ef6<\/span><\/div>\n              <div class=\"indent\"><span class=\"d\">includes\/<\/span> <span class=\"c\">\u2190 PHP \u8fd0\u884c\u65f6<\/span><\/div>\n              <div class=\"indent2\"><span class=\"f\">class-core.php<\/span><\/div>\n              <div class=\"indent2\"><span class=\"f\">class-admin.php<\/span><\/div>\n              <div class=\"indent\"><span class=\"d\">admin\/<\/span><\/div>\n              <div class=\"indent2\"><span class=\"d\" style=\"color:var(--amber);\">src\/<\/span> <span class=\"c\">\u2190 \u5728\u6b64\u5904\u7f16\u5199\u4ee3\u7801<\/span><\/div>\n              <div class=\"indent3\"><span class=\"x\">index.js<\/span> <span class=\"c\">\u2190 \u5165\u53e3\u70b9<\/span><\/div>\n              <div class=\"indent3\"><span class=\"f\">components\/<\/span><\/div>\n              <div class=\"indent2\"><span class=\"d\" style=\"color:var(--green);\">dist\/<\/span> <span class=\"c\">\u2190 \u6784\u5efa\u8f93\u51fa<\/span><\/div>\n              <div class=\"indent3\"><span class=\"x\">index.js<\/span><\/div>\n              <div class=\"indent3\"><span class=\"x\">index.asset.php<\/span><\/div>\n              <div class=\"indent3\"><span class=\"f\">index.css<\/span><\/div>\n              <div class=\"indent\"><span class=\"f\">languages\/<\/span> <span class=\"c\">\u2190 i18n<\/span><\/div>\n              <div class=\"indent\"><span class=\"i\">node_modules\/<\/span> <span class=\"c\">\u2190 .gitignore<\/span><\/div>\n              <div class=\"indent\"><span class=\"i\">releases\/<\/span> <span class=\"c\">\u2190 .gitignore<\/span><\/div>\n            <\/div>\n          <\/div>\n          <div class=\"tree-col\">\n            <div class=\"tree-label\">\u914d\u7f6e\u6587\u4ef6<\/div>\n            <div class=\"tree\">\n              <div><span class=\"x\">package.json<\/span><\/div>\n              <div><span class=\"f\">webpack.config.js<\/span> <span class=\"c\">\u2190 \u5982\u6709\u81ea\u5b9a\u4e49\u9700\u6c42<\/span><\/div>\n              <div><span class=\"x\">.gitignore<\/span><\/div>\n              <div><span class=\"x\">BUILD.md<\/span><\/div>\n              <div><span class=\"f\">readme.txt<\/span><\/div>\n              <div><span class=\"f\">uninstall.php<\/span><\/div>\n              <div style=\"margin-top:16px;background:var(--faint);border-radius:8px;padding:12px 14px;border:1px solid var(--border);\">\n                <div style=\"color:var(--muted);\">\/\/ \u2713 \u6b63\u786e \u2014 \u4ece dist \u52a0\u8f7d<\/div>\n                <div style=\"color:var(--green);\">plugins_url(<span style=\"color:var(--amber);\">\u2018admin\/dist\/index.js\u2019<\/span>)<\/div>\n                <div style=\"color:var(--muted);margin-top:8px;\">\/\/ \u2717 \u9519\u8bef \u2014 \u4e0d\u8981\u4ece src \u52a0\u8f7d<\/div>\n                <div style=\"color:var(--coral);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.5);\">plugins_url(<span style=\"color:var(--amber);\">\u2018admin\/src\/index.js\u2019<\/span>)<\/div>\n              <\/div>\n            <\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <!-- WORKFLOWS -->\n    <div class=\"flow-section fi\">\n      <div class=\"slabel\">\u5de5\u4f5c\u6d41<\/div>\n      <div class=\"flow-grid\">\n        <div class=\"fcard\">\n          <div class=\"fcard-head\">\n            <div class=\"tag t-green\"><span class=\"dot\"><\/span>Local Development<\/div>\n            <h3>\u672c\u5730\u5f00\u53d1<\/h3>\n            <p class=\"fcard-sub\">Ch\u1ea1y watch mode, s\u1eeda JS\/React \u2192 build t\u1ef1 \u0111\u1ed9ng, F5 WP l\u00e0 th\u1ea5y ngay.<\/p>\n          <\/div>\n          <div class=\"fcard-body\">\n            <div class=\"steps\">\n              <div class=\"step\"><div class=\"step-l\"><div class=\"step-dot t-green\">01<\/div><div class=\"step-line\"><\/div><\/div><div class=\"step-r\"><div class=\"step-title\">C\u00e0i dependencies<\/div><div class=\"step-desc\">\u53ea\u9700\u9996\u6b21\u3002\u8981\u6c42 Node.js \u2265 18\u3002.<\/div><div class=\"code\"><span class=\"cmd\">npm install<\/span><\/div><\/div><\/div>\n              <div class=\"step\"><div class=\"step-l\"><div class=\"step-dot t-green\">02<\/div><div class=\"step-line\"><\/div><\/div><div class=\"step-r\"><div class=\"step-title\">B\u1eadt watch mode<\/div><div class=\"step-desc\">Webpack \u76d1\u542c\uff1a\u5728 \u4e2d\u4fdd\u5b58\u6587\u4ef6 <code style=\"font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--amber);\">admin\/src\/<\/code> \u2192 t\u1ef1 build ra <code style=\"font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--green);\">admin\/dist\/<\/code>. \u5728 WP \u4e2d\u9700\u8981\u624b\u52a8\u6309 F5\u3002.<\/div><div class=\"code\"><span class=\"cmd\">npm run start<\/span><\/div><\/div><\/div>\n              <div class=\"step\"><div class=\"step-l\"><div class=\"step-dot t-green\">03<\/div><\/div><div class=\"step-r\"><div class=\"step-title\">\u5728\u672c\u5730 WP \u4e0a\u6d4b\u8bd5<\/div><div class=\"step-desc\">\u521b\u5efa\u7b26\u53f7\u94fe\u63a5\u5230 <code style=\"font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--slate);\">wp-content\/plugins\/<\/code> \u6216\u4f7f\u7528 Local by Flywheel\u3002.<\/div><\/div><\/div>\n            <\/div>\n          <\/div>\n        <\/div>\n        <div class=\"fcard\">\n          <div class=\"fcard-head\">\n            <div class=\"tag t-amber\"><span class=\"dot\"><\/span>Build &amp; Release<\/div>\n            <h3>\u6253\u5305 ZIP\uff0c\u5b89\u88c5 WP<\/h3>\n            <p class=\"fcard-sub\">\u6784\u5efa\u751f\u4ea7\u7248\uff0c\u6253\u5305\u5e72\u51c0\u7684 ZIP \u2014\u2014 \u670d\u52a1\u5668\u4e0a\u65e0\u9700 npm\u3002.<\/p>\n          <\/div>\n          <div class=\"fcard-body\">\n            <div class=\"steps\">\n              <div class=\"step\"><div class=\"step-l\"><div class=\"step-dot t-amber\">01<\/div><div class=\"step-line\"><\/div><\/div><div class=\"step-r\"><div class=\"step-title\">Build production<\/div><div class=\"step-desc\">Webpack \u6784\u5efa\uff0c\u5305\u542b\u538b\u7f29 + tree-shaking\u3002.<\/div><div class=\"code\"><span class=\"cmd\">npm run build<\/span><\/div><\/div><\/div>\n              <div class=\"step\"><div class=\"step-l\"><div class=\"step-dot t-amber\">02<\/div><div class=\"step-line\"><\/div><\/div><div class=\"step-r\"><div class=\"step-title\">\u6253\u5305 ZIP<\/div><div class=\"step-desc\">\u811a\u672c\u590d\u5236\u6b63\u786e\u6587\u4ef6\uff0c\u6392\u9664 <code style=\"font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--coral);\">node_modules<\/code> \u548c <code style=\"font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--coral);\">admin\/src<\/code>.<\/div><div class=\"code\"><span class=\"cmd\">npm run package<\/span><br><span class=\"cmt\"># \u2192 releases\/plugin-v1.0.0.zip<\/span><\/div><\/div><\/div>\n              <div class=\"step\"><div class=\"step-l\"><div class=\"step-dot t-amber\">03<\/div><div class=\"step-line\"><\/div><\/div><div class=\"step-r\"><div class=\"step-title\">\u6821\u9a8c SHA256<\/div><div class=\"code\"><span class=\"cmd\">sha256sum<\/span> <span class=\"val\">releases\/plugin-v1.0.0.zip<\/span><\/div><\/div><\/div>\n              <div class=\"step\"><div class=\"step-l\"><div class=\"step-dot\" style=\"color:var(--green);background:var(--green-bg);border-color:rgba(52,211,153,.25);\">\u2713<\/div><\/div><div class=\"step-r\"><div class=\"step-title\" style=\"color:var(--green);\">\u4e0a\u4f20\u5230 WordPress<\/div><div class=\"step-desc\">Admin \u2192 Plugins \u2192 Add New \u2192 Upload\u3002\u6fc0\u6d3b\u3002\u670d\u52a1\u5668\u4e0a\u65e0\u9700 npm\u3002.<\/div><\/div><\/div>\n            <\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <!-- NPM SCRIPTS -->\n    <div class=\"scripts-section fi\">\n      <div class=\"slabel\">npm \u811a\u672c \u2014 \u5907\u5fd8\u5355<\/div>\n      <div class=\"scripts-grid\">\n        <div class=\"scmd\"><div class=\"scmd-cmd\">npm run start<\/div><div class=\"scmd-what\">\u76d1\u542c\u6a21\u5f0f \u2014 \u65e5\u5e38\u5f00\u53d1<\/div><div class=\"scmd-detail\">webpack \u2013watch \u2013mode development<\/div><\/div>\n        <div class=\"scmd\"><div class=\"scmd-cmd\">npm run build<\/div><div class=\"scmd-what\">\u751f\u4ea7\u6784\u5efa \u2014 \u53d1\u5e03\u524d<\/div><div class=\"scmd-detail\">webpack \u2013mode production + minify<\/div><\/div>\n        <div class=\"scmd\"><div class=\"scmd-cmd\">npm run package<\/div><div class=\"scmd-what\">\u6253\u5305\u5e72\u51c0\u7684 ZIP \u5230 releases\/<\/div><div class=\"scmd-detail\">\u6392\u9664 src\/ node_modules\/ .git\/<\/div><\/div>\n        <div class=\"scmd\"><div class=\"scmd-cmd\">npm run lint:js<\/div><div class=\"scmd-what\">\u9075\u5faa WP \u6807\u51c6\u7684 JS \u4ee3\u7801\u68c0\u67e5<\/div><div class=\"scmd-detail\">wp-scripts lint-js<\/div><\/div>\n        <div class=\"scmd\"><div class=\"scmd-cmd\">npm run format<\/div><div class=\"scmd-what\">\u81ea\u52a8\u683c\u5f0f\u5316\u4ee3\u7801<\/div><div class=\"scmd-detail\">wp-scripts format (prettier)<\/div><\/div>\n        <div class=\"scmd\"><div class=\"scmd-cmd\">npm run release<\/div><div class=\"scmd-what\">Lint \u2192 \u6784\u5efa \u2192 \u6253\u5305<\/div><div class=\"scmd-detail\">\u5728\u4e00\u6761\u547d\u4ee4\u4e2d\u6267\u884c\u68c0\u67e5 + \u6784\u5efa + \u6253\u5305<\/div><\/div>\n      <\/div>\n    <\/div>\n\n    <!-- ZIP CONTENTS -->\n    <div class=\"zip-section fi\">\n      <div class=\"slabel\">ZIP \u53d1\u5e03\u5305 \u2014 \u5185\u90e8\u4e0e\u5916\u90e8<\/div>\n      <div class=\"zip-grid\">\n        <div class=\"zip-card\">\n          <div class=\"zip-head\"><span class=\"tag t-green\"><span class=\"dot\"><\/span>\u2713 ZIP \u5305\u4e2d\u5305\u542b<\/span><\/div>\n          <div class=\"zip-body\">\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--green);\">my-plugin.php<\/span><span class=\"zip-note\">\u4e3b\u63d2\u4ef6\u6587\u4ef6<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--green);\">includes\/<\/span><span class=\"zip-note\">\u5b8c\u6574\u7684 PHP \u8fd0\u884c\u65f6\u6587\u4ef6<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--green);\">admin\/dist\/<\/span><span class=\"zip-note\">\u5df2\u6784\u5efa\u597d\u7684 JS\/CSS<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--green);\">languages\/<\/span><span class=\"zip-note\">i18n \u8bed\u8a00\u5305\uff08\u5982\u6709\uff09<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--green);\">readme.txt<\/span><span class=\"zip-note\">WP.org \u683c\u5f0f<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--green);\">uninstall.php<\/span><span class=\"zip-note\">\u5220\u9664\u63d2\u4ef6\u65f6\u7684\u6e05\u7406\u811a\u672c<\/span><\/div>\n          <\/div>\n        <\/div>\n        <div class=\"zip-card\">\n          <div class=\"zip-head\"><span class=\"tag t-coral\"><span class=\"dot\"><\/span>\u2717 ZIP \u5305\u4e2d\u4e0d\u5305\u542b<\/span><\/div>\n          <div class=\"zip-body\">\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--coral);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.4);\">node_modules\/<\/span><span class=\"zip-note\">\u4f9d\u8d56\u4ec5\u7528\u4e8e\u5f00\u53d1<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--coral);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.4);\">admin\/src\/<\/span><span class=\"zip-note\">\u6e90\u7801\uff0c\u4e0d\u8fd0\u884c<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--coral);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.4);\">.git\/<\/span><span class=\"zip-note\">\u4ed3\u5e93\u5143\u6570\u636e<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--coral);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.4);\">package.json \/ webpack.config.js<\/span><span class=\"zip-note\">\u6784\u5efa\u914d\u7f6e<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--coral);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.4);\">.test.js \/ debug-.php<\/span><span class=\"zip-note\">\u5185\u90e8\u6d4b\u8bd5\u6587\u4ef6<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--coral);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.4);\">.env \/ .DS_Store<\/span><span class=\"zip-note\">\u672c\u5730\u673a\u5668\u6587\u4ef6<\/span><\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <!-- DO \/ DON'T -->\n    <div class=\"fi\" style=\"margin-bottom:56px;\">\n      <div class=\"slabel\">\u91cd\u8981\u89c4\u5219<\/div>\n      <div class=\"dodonts\">\n        <div class=\"do-col\">\n          <div class=\"do-head\">\u6b63\u786e\u505a\u6cd5<\/div>\n          <div class=\"do-item\">\u5165\u961f\u81ea <code style=\"font-family:'JetBrains Mono',monospace;\">admin\/dist\/<\/code><\/div>\n          <div class=\"do-item\">\u8bfb\u53d6 <code style=\"font-family:'JetBrains Mono',monospace;\">index.asset.php<\/code> \u83b7\u53d6\u4f9d\u8d56 + \u7248\u672c<\/div>\n          <div class=\"do-item\">\u4f7f\u7528 <code style=\"font-family:'JetBrains Mono',monospace;\">wp_localize_script()<\/code> \u4f20\u9012\u6570\u636e PHP \u2192 JS<\/div>\n          <div class=\"do-item\">\u5f00\u5c55 <code style=\"font-family:'JetBrains Mono',monospace;\">npm run build<\/code> \u4e4b\u524d <code style=\"font-family:'JetBrains Mono',monospace;\">npm run package<\/code><\/div>\n          <div class=\"do-item\">\u6309\u6761\u4ef6\u52a0\u8f7d \u2014\u2014 \u4ec5\u5728\u9700\u8981\u7684\u9875\u9762 enqueue<\/div>\n          <div class=\"do-item\">\u5168\u90e8\u6dfb\u52a0\u524d\u7f00\uff1a <code style=\"font-family:'JetBrains Mono',monospace;\">dps_<\/code>, <code style=\"font-family:'JetBrains Mono',monospace;\">DPS_<\/code><\/div>\n        <\/div>\n        <div class=\"dont-col\">\n          <div class=\"dont-head\">\u4e0d\u8981\u505a<\/div>\n          <div class=\"dont-item\">\u5165\u961f\u81ea <code style=\"font-family:'JetBrains Mono',monospace;\">admin\/src\/<\/code><\/div>\n          <div class=\"dont-item\">\u5728 PHP \u4e2d\u786c\u7f16\u7801\u7248\u672c\u54c8\u5e0c<\/div>\n          <div class=\"dont-item\">\u4e3a\u4e86 <code style=\"font-family:'JetBrains Mono',monospace;\">node_modules\/<\/code> \u5728 ZIP \u4e2d<\/div>\n          <div class=\"dont-item\">\u5728\u751f\u4ea7\u670d\u52a1\u5668\u4e0a\u6267\u884c npm install<\/div>\n          <div class=\"dont-item\">\u5728\u6b64\u5904\u6267\u884c\u91cd\u91cf\u7ea7 DB \u67e5\u8be2 <code style=\"font-family:'JetBrains Mono',monospace;\">init<\/code> hook<\/div>\n          <div class=\"dont-item\"><code style=\"font-family:'JetBrains Mono',monospace;\">echo $_POST['x']<\/code> \u672a\u8fdb\u884c sanitize\/escape<\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <!-- CHECKLIST -->\n    <div class=\"ac-section fi\">\n      <div class=\"slabel\">\u751f\u4ea7\u5c31\u7eea\u6e05\u5355<\/div>\n      <div style=\"display:grid;grid-template-columns:1fr 1fr;gap:6px;\">\n        <div style=\"display:flex;flex-direction:column;gap:6px;\">\n          <div style=\"font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--blue);padding:4px 0 8px;\">Build &amp; Release<\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\"><code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green);\">npm run build<\/code> \u65e0\u9519\u8bef \u2192 <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green);\">admin\/dist\/<\/code><\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">ZIP \u53ef\u5b89\u88c5\uff0c\u6fc0\u6d3b\u65e0\u9519\u8bef \u2014\u2014 \u65e0\u9700 npm \u670d\u52a1\u5668<\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">ZIP \u4e0d\u5305\u542b <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--coral);\">node_modules\/<\/code> \u8fd8\u662f <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--coral);\">src\/<\/code><\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">\u53cd\u9988\uff1a\u6587\u4ef6\u5217\u8868 + ZIP \u8def\u5f84 + SHA256<\/div><\/div>\n          <div style=\"font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--purple);padding:12px 0 8px;\">\u5b89\u5168<\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">\u6240\u6709 PHP \u6587\u4ef6\u90fd\u6709 <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--purple);\">if (!defined('ABSPATH')) exit;<\/code><\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">\u6240\u6709 AJAX\/form\uff1anonce \u6821\u9a8c + <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--purple);\">current_user_can()<\/code><\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">\u8f93\u5165\u5df2\u6e05\u7406\uff0c\u8f93\u51fa\u5df2\u8f6c\u4e49<\/div><\/div>\n        <\/div>\n        <div style=\"display:flex;flex-direction:column;gap:6px;\">\n          <div style=\"font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--amber);padding:4px 0 8px;\">\u6548\u679c<\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">\u8d44\u6e90\u6309\u6761\u4ef6\u52a0\u8f7d \u2014\u2014 \u4e0d\u5728\u5168\u7ad9\u52a0\u8f7d<\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">\u811a\u672c\uff1a <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--amber);\">in_footer: true<\/code> + <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--amber);\">strategy: defer<\/code><\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">\u4e0d\u8981\u5728\u6b64\u5904\u6267\u884c\u91cd\u91cf\u7ea7 DB \u67e5\u8be2 <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--amber);\">init<\/code> hook<\/div><\/div>\n          <div style=\"font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--green);padding:12px 0 8px;\">\u89c4\u8303<\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">\u6240\u6709 function\/class\/option \u90fd\u6709\u524d\u7f00 <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green);\">dps_<\/code><\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">\u63d2\u4ef6\u5934\uff1a <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green);\">\u6700\u4f4e\u8981\u6c42<\/code>, <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green);\">PHP \u7248\u672c\u8981\u6c42<\/code><\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">\u6240\u6709\u5b57\u7b26\u4e32\u4f7f\u7528 i18n\uff0c, <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green);\">uninstall.php<\/code> \u6e05\u7406\u5e72\u51c0<\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\"><code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green);\">BUILD.md<\/code> \u5b8c\u6574\uff1ainstall, build, package, test<\/div><\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n\n  <\/div><!-- \/dps-page -->\n\n  <!-- BOTTOM BAR -->\n  <div class=\"dps-footer\">\n    <div class=\"dps-footer-l\">\n      <div class=\"dps-logo\">D<\/div>\n      <p>DPS.MEDIA \u80a1\u4efd\u516c\u53f8 \u00b7 \u7a0e\u53f7 0318700500<\/p>\n    <\/div>\n    <div class=\"dps-footer-links\">\n      <a href=\"mailto:marketing@dps.media\">marketing@dps.media<\/a>\n      <a href=\"tel:0961545445\">0961 545 445<\/a>\n      <a href=\"https:\/\/dps.media\/zh\/\">dps.media<\/a>\n    <\/div>\n  <\/div>\n\n<\/div><!-- \/#dps-guide --><script>\n(function(){\n  var guide = document.getElementById('dps-guide');\n  if(!guide) return;\n\n  \/\/ Fade-in on scroll\n  var io = new IntersectionObserver(function(es){\n    es.forEach(function(e){ if(e.isIntersecting){ e.target.classList.add('in'); io.unobserve(e.target); } });\n  },{threshold:0.05});\n  guide.querySelectorAll('.fi').forEach(function(el,i){\n    el.style.transitionDelay=(i*0.06)+'s';\n    io.observe(el);\n  });\n\n  \/\/ Copy button\n  var btn = document.getElementById('dps-copy-btn');\n  var lbl = document.getElementById('dps-copy-label');\n  if(!btn) return;\n\n  btn.addEventListener('click', function(){\n    var md = \"# WP Plugin Dev \\u2014 Agent Prompt (DPS.MEDIA)\\n\\n## M\\u1ee5c ti\\u00eau\\nRefactor plugin sang flow **source \\u2192 build \\u2192 release**. Plugin ph\\u1ea3i: load nhanh, kh\\u00f4ng conflict, \\u0111\\u00fang WP coding standards, b\\u1ea3o m\\u1eadt, d\\u1ec5 b\\u1ea3o tr\\u00ec.\\n\\n---\\n\\n## 0. \\u0110\\u00e1nh gi\\u00e1 tr\\u01b0\\u1edbc khi b\\u1eaft \\u0111\\u1ea7u (YAGNI check)\\n\\nTr\\u01b0\\u1edbc khi refactor b\\u1ea5t k\\u1ef3 th\\u1ee9 g\\u00ec, ki\\u1ec3m tra t\\u1eebng th\\u01b0 m\\u1ee5c asset v\\u00e0 t\\u1ef1 \\u0111\\u00e1nh gi\\u00e1:\\n\\n- `admin\/` \\u2014 c\\u00f3 React\/JSX\/TS, import ES module, Sass? \\u2192 \\u0111\\u01b0a v\\u00e0o pipeline\\n- `public\/` \\u2014 ch\\u1ec9 vanilla JS\/jQuery\/CSS thu\\u1ea7n? \\u2192 gi\\u1eef static, kh\\u00f4ng build\\n\\n\\u00c1p d\\u1ee5ng **YAGNI** \\u2014 ch\\u1ec9 build nh\\u1eefng g\\u00ec th\\u1ef1c s\\u1ef1 c\\u1ea7n transpile. B\\u00e1o l\\u1ea1i quy\\u1ebft \\u0111\\u1ecbnh tr\\u01b0\\u1edbc khi vi\\u1ebft code.\\n\\n---\\n\\n## 1. C\\u1ea5u tr\\u00fac th\\u01b0 m\\u1ee5c\\n```\\nmy-plugin\/\\n\\u251c\\u2500\\u2500 my-plugin.php\\n\\u251c\\u2500\\u2500 includes\/\\n\\u251c\\u2500\\u2500 admin\/\\n\\u2502   \\u251c\\u2500\\u2500 src\/     \\u2190 vi\\u1ebft code \\u1edf \\u0111\\u00e2y\\n\\u2502   \\u2514\\u2500\\u2500 dist\/    \\u2190 PHP enqueue t\\u1eeb \\u0111\\u00e2y\\n\\u251c\\u2500\\u2500 languages\/\\n\\u251c\\u2500\\u2500 releases\/  (.gitignore)\\n\\u251c\\u2500\\u2500 package.json\\n\\u251c\\u2500\\u2500 .gitignore\\n\\u2514\\u2500\\u2500 BUILD.md\\n```\\n\\n## 2. Plugin file header\\n```php\\n\/**\\n * Plugin Name: My Plugin\\n * Requires at least: 6.0\\n * Requires PHP: 8.0\\n * Tested up to: 6.7\\n * Text Domain: my-plugin\\n *\/\\nif (!defined('ABSPATH')) exit;\\n```\\n\\n## 3. npm scripts\\n```json\\n{\\n  \\\"start\\\":   \\\"wp-scripts start\\\",\\n  \\\"build\\\":   \\\"wp-scripts build\\\",\\n  \\\"package\\\": \\\"node scripts\/package.js\\\",\\n  \\\"lint:js\\\": \\\"wp-scripts lint-js admin\/src\\\",\\n  \\\"check\\\":   \\\"npm run lint:js && npm run lint:css\\\",\\n  \\\"release\\\": \\\"npm run check && npm run build && npm run package\\\"\\n}\\n```\\n\\n## 4. PHP enqueue \\u2014 chu\\u1ea9n\\n```php\\nadd_action('admin_enqueue_scripts', function($hook) {\\n  if ($hook !== 'toplevel_page_my-plugin') return; \/\/ conditional\\n  $asset = include plugin_dir_path(__FILE__) . 'admin\/dist\/index.asset.php';\\n  wp_enqueue_script('my-plugin', plugins_url('admin\/dist\/index.js', __FILE__),\\n    $asset['dependencies'], $asset['version'],\\n    ['in_footer' => true, 'strategy' => 'defer']);\\n  wp_localize_script('my-plugin', 'dpsData', [\\n    'nonce' => wp_create_nonce('dps_nonce')\\n  ]);\\n});\\n```\\n\\n## 5. Security\\n```php\\n\/\/ \\u0110\\u1ea7u m\\u1ecdi file PHP\\nif (!defined('ABSPATH')) exit;\\n\\n\/\/ Prefix t\\u1ea5t c\\u1ea3\\nfunction dps_get_settings() {}\\nclass DPS_Plugin_Core {}\\n\\n\/\/ AJAX handler\\nfunction dps_handle_ajax() {\\n  check_ajax_referer('dps_nonce', 'nonce');\\n  if (!current_user_can('manage_options')) wp_die('Unauthorized', 403);\\n  $name = sanitize_text_field($_POST['name']);\\n  echo esc_html($name);\\n  wp_die();\\n}\\n```\\n\\n## 6. ZIP release\\nCo trong ZIP: my-plugin.php, includes\/, admin\/dist\/, languages\/, readme.txt, uninstall.php\\nKHONG co: node_modules\/, admin\/src\/, .git\/, package.json, *.test.js\\n\\n## 7. Acceptance criteria\\n- [ ] npm run build khong loi, output ra admin\/dist\/\\n- [ ] ZIP cai duoc, Activate khong loi, khong can npm tren server\\n- [ ] ZIP khong chua node_modules\/ hay admin\/src\/\\n- [ ] Bao lai: danh sach file + ZIP path + SHA256\\n- [ ] Moi file PHP co: if (!defined('ABSPATH')) exit;\\n- [ ] Moi AJAX\/form: nonce verify + current_user_can()\\n- [ ] Input sanitized, output escaped\\n- [ ] Asset load conditional, script defer\\n- [ ] Prefix dps_ cho moi function\/class\/option\\n- [ ] Plugin header day du fields\\n- [ ] uninstall.php cleanup sach\\n- [ ] BUILD.md day du\\n\";\n\n    try {\n      var ta = document.createElement('textarea');\n      ta.value = md;\n      ta.style.cssText = 'position:fixed;top:-9999px;left:-9999px;opacity:0;';\n      document.body.appendChild(ta);\n      ta.focus(); ta.select();\n      document.execCommand('copy');\n      document.body.removeChild(ta);\n      btn.classList.add('copied');\n      lbl.textContent = 'Copied!';\n      setTimeout(function(){ btn.classList.remove('copied'); lbl.textContent = 'Copy agent prompt'; }, 2200);\n    } catch(e) {\n      lbl.textContent = 'Failed';\n      setTimeout(function(){ lbl.textContent = 'Copy agent prompt'; }, 2000);\n    }\n  });\n})();\n<\/script>\n<style>\r\n.lwrp.link-whisper-related-posts{\r\n            \r\n            margin-top: 40px;\nmargin-bottom: 30px;\r\n        }\r\n        .lwrp .lwrp-title{\r\n            \r\n            \r\n        }.lwrp .lwrp-description{\r\n            \r\n            \r\n\r\n        }\r\n        .lwrp .lwrp-list-container{\r\n        }\r\n        .lwrp .lwrp-list-multi-container{\r\n            display: flex;\r\n        }\r\n        .lwrp .lwrp-list-double{\r\n            width: 48%;\r\n        }\r\n        .lwrp .lwrp-list-triple{\r\n            width: 32%;\r\n        }\r\n        .lwrp .lwrp-list-row-container{\r\n            display: flex;\r\n            justify-content: space-between;\r\n        }\r\n        .lwrp .lwrp-list-row-container .lwrp-list-item{\r\n            width: calc(33% - 20px);\r\n        }\r\n        .lwrp .lwrp-list-item:not(.lwrp-no-posts-message-item){\r\n            \r\n            max-width: 150px;\r\n        }\r\n        .lwrp .lwrp-list-item img{\r\n            max-width: 100%;\r\n            height: auto;\r\n            object-fit: cover;\r\n            aspect-ratio: 1 \/ 1;\r\n        }\r\n        .lwrp .lwrp-list-item.lwrp-empty-list-item{\r\n            background: initial !important;\r\n        }\r\n        .lwrp .lwrp-list-item .lwrp-list-link .lwrp-list-link-title-text,\r\n        .lwrp .lwrp-list-item .lwrp-list-no-posts-message{\r\n            \r\n            \r\n            \r\n            \r\n        }@media screen and (max-width: 480px) {\r\n            .lwrp.link-whisper-related-posts{\r\n                \r\n                \r\n            }\r\n            .lwrp .lwrp-title{\r\n                \r\n                \r\n            }.lwrp .lwrp-description{\r\n                \r\n                \r\n            }\r\n            .lwrp .lwrp-list-multi-container{\r\n                flex-direction: column;\r\n            }\r\n            .lwrp .lwrp-list-multi-container ul.lwrp-list{\r\n                margin-top: 0px;\r\n                margin-bottom: 0px;\r\n                padding-top: 0px;\r\n                padding-bottom: 0px;\r\n            }\r\n            .lwrp .lwrp-list-double,\r\n            .lwrp .lwrp-list-triple{\r\n                width: 100%;\r\n            }\r\n            .lwrp .lwrp-list-row-container{\r\n                justify-content: initial;\r\n                flex-direction: column;\r\n            }\r\n            .lwrp .lwrp-list-row-container .lwrp-list-item{\r\n                width: 100%;\r\n            }\r\n            .lwrp .lwrp-list-item:not(.lwrp-no-posts-message-item){\r\n                \r\n                max-width: initial;\r\n            }\r\n            .lwrp .lwrp-list-item .lwrp-list-link .lwrp-list-link-title-text,\r\n            .lwrp .lwrp-list-item .lwrp-list-no-posts-message{\r\n                \r\n                \r\n                \r\n                \r\n            };\r\n        }<\/style>\r\n<div id=\"link-whisper-related-posts-widget\" class=\"link-whisper-related-posts lwrp\">\r\n            <div class=\"lwrp-title\">\u76f8\u5173\u6587\u7ae0<\/div>    \r\n        <div class=\"lwrp-list-container\">\r\n                                <div class=\"lwrp-list lwrp-list-row-container lwrp-list-double-row\">\r\n                <div class=\"lwrp-list-item\"><a href=\"https:\/\/dps.media\/zh\/wp-mcp-connect-giai-phap-all-in-one-ket-noi-ai-agents-voi-wordpress\/\" class=\"lwrp-list-link\"><span class=\"lwrp-list-link-title-text\">WP MCP Connect\uff1a\u8fde\u63a5 AI Agents \u4e0e WordPress \u7684\u201cAll-in-One\u201d\u89e3\u51b3\u65b9\u6848<\/span><\/a><\/div><div class=\"lwrp-list-item\"><a href=\"https:\/\/dps.media\/zh\/100%e5%ae%89%e5%85%a8%e5%8f%af%e9%9d%a0%e7%9a%84tiktok%e9%a2%91%e9%81%93%e4%b9%b0%e5%8d%96%e6%9c%8d%e5%8a%a1\/\" class=\"lwrp-list-link\"><span class=\"lwrp-list-link-title-text\">\u4fe1\u8a89\u3001\u5b89\u5168\u7684TikTok\u9891\u9053\u4e70\u5356\u670d\u52a1100%<\/span><\/a><\/div><div class=\"lwrp-list-item\"><a href=\"https:\/\/dps.media\/zh\/facebook-%e7%a7%8d%e5%ad%90%e6%9c%8d%e5%8a%a1-%e4%be%bf%e5%ae%9c%e5%a5%97%e9%a4%90-%e8%b5%a0%e9%80%81%e7%82%b9%e8%b5%9e%e8%af%84%e8%ae%ba\/\" class=\"lwrp-list-link\"><span class=\"lwrp-list-link-title-text\">Facebook\u79cd\u5b50\u670d\u52a1\u4f4e\u4ef7\u5957\u9910 - \u589e\u52a0\u70b9\u8d5e\u3001\u8bc4\u8bba<\/span><\/a><\/div>                <\/div>\r\n                            <div class=\"lwrp-list lwrp-list-row-container lwrp-list-double-row\">\r\n                <div class=\"lwrp-list-item\"><a href=\"https:\/\/dps.media\/zh\/%e5%8d%81%e5%a4%a7%e6%9c%80%e5%8f%97%e4%bf%a1%e8%b5%96%e7%9a%84%e4%bc%81%e4%b8%9a%e7%bd%91%e7%ab%99%e8%ae%be%e8%ae%a1%e5%85%ac%e5%8f%b8\/\" class=\"lwrp-list-link\"><span class=\"lwrp-list-link-title-text\">\u5341\u5927\u4f01\u4e1a\u7f51\u7ad9\u8bbe\u8ba1\u516c\u53f8\u6df1\u53d7\u4fe1\u8d56<\/span><\/a><\/div><div class=\"lwrp-list-item\"><a href=\"https:\/\/dps.media\/zh\/%e5%a6%82%e4%bd%95%e5%bb%ba%e7%ab%8btiktok%e7%a4%be%e5%8c%ba%e4%bb%a5%e7%95%99%e4%bd%8f%e5%ae%a2%e6%88%b7\/\" class=\"lwrp-list-link\"><span class=\"lwrp-list-link-title-text\">\u5982\u4f55\u6784\u5efaTikTok\u793e\u533a\u4ee5\u7559\u4f4f\u5ba2\u6237<\/span><\/a><\/div><div class=\"lwrp-list-item\"><a href=\"https:\/\/dps.media\/zh\/%e5%85%ac%e5%8f%b8%e8%ae%be%e8%ae%a1%e5%b9%bf%e5%91%8a%e6%89%93%e9%80%a0%e7%a8%b3%e5%9b%ba%e5%93%81%e7%89%8c%e7%9a%84%e8%83%bd%e5%8a%9b%e6%a1%a3%e6%a1%88\/\" class=\"lwrp-list-link\"><span class=\"lwrp-list-link-title-text\">\u5e7f\u544a\u8bbe\u8ba1\u516c\u53f8\u80fd\u529b\u7b80\u4ecb\u2014\u2014\u6253\u9020\u53ef\u6301\u7eed\u54c1\u724c<\/span><\/a><\/div>                <\/div>\r\n                <\/div>\r\n<\/div>","protected":false},"excerpt":{"rendered":"<p>D DPS.MEDIA WP Plugin Dev Guide \u2014 Internal Copy agent prompt H Hi\u1ec3n CEO \u00b7 DPS.MEDIA WordPressPlugin DevGuide Flow source \u2192 build \u2192 release cho team. \u0110\u1ee7 \u0111\u1ec3 dev local, \u0111\u00f3ng ZIP, c\u00e0i l\u00ean WordPress production. PHP 8.x WordPress hooks API @wordpress\/scripts React (Admin UI) Webpack 5 npm scripts Node.js \u2265 18 ZIP release C\u1ea5u [&hellip;]<\/p>","protected":false},"author":1,"featured_media":37957,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1,1204],"tags":[],"class_list":["post-37956","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","category-wordpress-marketing"],"acf":[],"rankmath_keywords":{"primary":"","secondary":[""]},"yoast_keywords":{"primary":"","secondary":[]},"yoast_focuskw":"","rankmath_focuskw":"","seo_keywords":{"primary":"","secondary":[""]},"_links":{"self":[{"href":"http:\/\/dps.media\/zh\/wp-json\/wp\/v2\/posts\/37956","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/dps.media\/zh\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/dps.media\/zh\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/dps.media\/zh\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/dps.media\/zh\/wp-json\/wp\/v2\/comments?post=37956"}],"version-history":[{"count":4,"href":"http:\/\/dps.media\/zh\/wp-json\/wp\/v2\/posts\/37956\/revisions"}],"predecessor-version":[{"id":37961,"href":"http:\/\/dps.media\/zh\/wp-json\/wp\/v2\/posts\/37956\/revisions\/37961"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/dps.media\/zh\/wp-json\/wp\/v2\/media\/37957"}],"wp:attachment":[{"href":"http:\/\/dps.media\/zh\/wp-json\/wp\/v2\/media?parent=37956"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/dps.media\/zh\/wp-json\/wp\/v2\/categories?post=37956"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/dps.media\/zh\/wp-json\/wp\/v2\/tags?post=37956"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}