Changeset 3713964
- Timestamp:
- 09/26/2026 07:45:24 AM (3 weeks ago)
- Location:
- readystack-payroll-tax-spreadsheet
- Files:
-
- 14 edited
- 1 copied
-
tags/1.0.2 (copied) (copied from readystack-payroll-tax-spreadsheet/trunk )
-
tags/1.0.2/assets/tool-1.js (modified) (1 diff)
-
tags/1.0.2/assets/tool-2.js (modified) (1 diff)
-
tags/1.0.2/assets/tool-3.js (modified) (3 diffs)
-
tags/1.0.2/assets/tool-4.js (modified) (2 diffs)
-
tags/1.0.2/assets/tool.css (modified) (1 diff)
-
tags/1.0.2/readme.txt (modified) (3 diffs)
-
tags/1.0.2/readystack-payroll-tax-spreadsheet.php (modified) (2 diffs)
-
trunk/assets/tool-1.js (modified) (1 diff)
-
trunk/assets/tool-2.js (modified) (1 diff)
-
trunk/assets/tool-3.js (modified) (3 diffs)
-
trunk/assets/tool-4.js (modified) (2 diffs)
-
trunk/assets/tool.css (modified) (1 diff)
-
trunk/readme.txt (modified) (3 diffs)
-
trunk/readystack-payroll-tax-spreadsheet.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
readystack-payroll-tax-spreadsheet/tags/1.0.2/assets/tool-1.js
r3712579 r3713964 1 (function(){var s=document.createElement("script");s.type="application/json";s.id="calcdata";s.textContent="{\"spec\": {\"sheets\": [{\"name\": \"Inputs - Your Payroll Numbers\", \"purpose\": \"Type your own eight numbers here; both calc sheets recalculate. A free online paycheck calculator cannot carry year-to-date wages from one run to the next, so it never knows that Social Security has already stopped for this employee — that is the whole reason this file exists. Rates you must confirm yourself are inputs, not guesses: the Social Security wage base is set by the SSA each October and the default shown is the 2025 figure of 176,100, so replace it with the figure for the year you are running. The $7,000 FUTA base is statutory. Your state UI rate and state UI taxable wage base come from your state agency's annual notice and differ in every state. Excel: open the file. Google Sheets: File, Import, Upload, Replace spreadsheet.\", \"inputs\": [{\"label\": \"Gross wages this pay period, one employee\", \"key\": \"gross_wages_this_period\", \"value\": 3000, \"format\": \"currency\"}, {\"label\": \"Wages already paid to this employee this year, before this period\", \"key\": \"ytd_wages_before_this_period\", \"value\": 6000, \"format\": \"currency\"}, {\"label\": \"Federal income tax withheld this period (from IRS Publication 15-T)\", \"key\": \"federal_income_tax_withheld\", \"value\": 316, \"format\": \"currency\"}, {\"label\": \"Social Security wage base for your tax year (SSA notice; 2025 figure shown)\", \"key\": \"social_security_wage_base\", \"value\": 176100, \"format\": \"currency\"}, {\"label\": \"FUTA wage base per employee per year (statutory)\", \"key\": \"futa_wage_base\", \"value\": 7000, \"format\": \"currency\"}, {\"label\": \"FUTA net rate after the 5.4% state credit (use 6.0% in a credit-reduction state)\", \"key\": \"futa_net_rate\", \"value\": 0.006, \"format\": \"percent\"}, {\"label\": \"Your state UI taxable wage base (from your state agency notice)\", \"key\": \"state_ui_wage_base\", \"value\": 7000, \"format\": \"currency\"}, {\"label\": \"Your assigned state UI rate for this year (from your state agency notice)\", \"key\": \"state_ui_rate\", \"value\": 0.034, \"format\": \"percent\"}]}, {\"name\": \"1. This Paycheck (Employee)\", \"purpose\": \"One question, answered completely: what comes out of this paycheck. Social Security stops at the wage base, Medicare never stops, and the extra 0.9% starts only after $200,000 of wages in the calendar year — employers withhold that 0.9% at $200,000 regardless of the employee's filing status, and do not match it (IRS Publication 15). Charge 6.2% on wages above the base and you over-withhold: the employee recovers it on their 1040, but your Form 941 no longer ties out and the correction lands on you. Net pay here is before state income tax and any benefit deductions.\", \"calc_rows\": [{\"label\": \"Wages subject to Social Security this period (capped at the wage base)\", \"key\": \"ss_taxable_wages\", \"formula\": \"=MIN({gross_wages_this_period},MAX(0,{social_security_wage_base}-{ytd_wages_before_this_period}))\"}, {\"label\": \"Social Security withheld from the employee at 6.2%\", \"key\": \"ss_withheld_employee\", \"formula\": \"=ROUND({ss_taxable_wages}*0.062,2)\"}, {\"label\": \"Medicare withheld from the employee at 1.45% (no wage cap)\", \"key\": \"medicare_withheld_employee\", \"formula\": \"=ROUND({gross_wages_this_period}*0.0145,2)\"}, {\"label\": \"Additional Medicare withheld at 0.9% on wages over $200,000 year to date\", \"key\": \"additional_medicare_withheld\", \"formula\": \"=ROUND((MAX(0,{ytd_wages_before_this_period}+{gross_wages_this_period}-200000)-MAX(0,{ytd_wages_before_this_period}-200000))*0.009,2)\"}, {\"label\": \"Total withheld from this paycheck, income tax plus FICA\", \"key\": \"employee_taxes_withheld_total\", \"formula\": \"=ROUND({federal_income_tax_withheld}+{ss_withheld_employee}+{medicare_withheld_employee}+{additional_medicare_withheld},2)\"}, {\"label\": \"Net pay before state income tax and benefit deductions\", \"key\": \"net_pay_this_period\", \"formula\": \"=ROUND({gross_wages_this_period}-{employee_taxes_withheld_total},2)\"}]}]}, \"lang\": \"en\", \"locale\": \"en-US\", \"currency\": \"USD\", \"paid\": \"\", \"slug\": \"payroll-tax-spreadsheet\", \"ui\": {\"inputs\": \"Your numbers\", \"results\": \"Your result\", \"recalc\": \"Everything updates as you type.\", \"get\": \"Get the full calculator\", \"email\": \"Email me the full version\", \"placeholder\": \"you@example.com\", \"sent\": \"Sent. Check your inbox.\", \"share\": \"Save result image\", \"copy\": \"Copy link\", \"copied\": \"Link copied\", \"more\": \"Full version: all tabs, your own file, works offline.\", \"free\": \"Free calculator\", \"note\": \"Nothing is uploaded. This runs in your browser.\", \"dl\": \"Download my numbers (CSV)\", \"dl_need\": \"Enter your email above and we will unlock the download.\", \"dl_done\": \"Downloaded.\"}, \"title\": \"Payroll Tax Spreadsheet for US Small Employers — FICA, FUTA and State UI Wage-Base Caps per Paycheck\"}";document.body.appendChild(s);})(); 1 (function () { 2 var s = document.createElement("script"); 3 s.type = "application/json"; 4 s.id = "calcdata"; 5 s.textContent = JSON.stringify({ 6 spec: { 7 sheets: [ 8 { 9 name: "Inputs - Your Payroll Numbers", 10 purpose: 11 "Type your own eight numbers here; both calc sheets recalculate. A free online paycheck calculator cannot carry year-to-date wages from one run to the next, so it never knows that Social Security has already stopped for this employee — that is the whole reason this file exists. Rates you must confirm yourself are inputs, not guesses: the Social Security wage base is set by the SSA each October and the default shown is the 2025 figure of 176,100, so replace it with the figure for the year you are running. The $7,000 FUTA base is statutory. Your state UI rate and state UI taxable wage base come from your state agency's annual notice and differ in every state. Excel: open the file. Google Sheets: File, Import, Upload, Replace spreadsheet.", 12 inputs: [ 13 { 14 label: "Gross wages this pay period, one employee", 15 key: "gross_wages_this_period", 16 value: 3000, 17 format: "currency", 18 }, 19 { 20 label: "Wages already paid to this employee this year, before this period", 21 key: "ytd_wages_before_this_period", 22 value: 6000, 23 format: "currency", 24 }, 25 { 26 label: "Federal income tax withheld this period (from IRS Publication 15-T)", 27 key: "federal_income_tax_withheld", 28 value: 316, 29 format: "currency", 30 }, 31 { 32 label: "Social Security wage base for your tax year (SSA notice; 2025 figure shown)", 33 key: "social_security_wage_base", 34 value: 176100, 35 format: "currency", 36 }, 37 { 38 label: "FUTA wage base per employee per year (statutory)", 39 key: "futa_wage_base", 40 value: 7000, 41 format: "currency", 42 }, 43 { 44 label: 45 "FUTA net rate after the 5.4% state credit (use 6.0% in a credit-reduction state)", 46 key: "futa_net_rate", 47 value: 0.006, 48 format: "percent", 49 }, 50 { 51 label: "Your state UI taxable wage base (from your state agency notice)", 52 key: "state_ui_wage_base", 53 value: 7000, 54 format: "currency", 55 }, 56 { 57 label: "Your assigned state UI rate for this year (from your state agency notice)", 58 key: "state_ui_rate", 59 value: 0.034, 60 format: "percent", 61 }, 62 ], 63 }, 64 { 65 name: "1. This Paycheck (Employee)", 66 purpose: 67 "One question, answered completely: what comes out of this paycheck. Social Security stops at the wage base, Medicare never stops, and the extra 0.9% starts only after $200,000 of wages in the calendar year — employers withhold that 0.9% at $200,000 regardless of the employee's filing status, and do not match it (IRS Publication 15). Charge 6.2% on wages above the base and you over-withhold: the employee recovers it on their 1040, but your Form 941 no longer ties out and the correction lands on you. Net pay here is before state income tax and any benefit deductions.", 68 calc_rows: [ 69 { 70 label: "Wages subject to Social Security this period (capped at the wage base)", 71 key: "ss_taxable_wages", 72 formula: 73 "=MIN({gross_wages_this_period},MAX(0,{social_security_wage_base}-{ytd_wages_before_this_period}))", 74 }, 75 { 76 label: "Social Security withheld from the employee at 6.2%", 77 key: "ss_withheld_employee", 78 formula: "=ROUND({ss_taxable_wages}*0.062,2)", 79 }, 80 { 81 label: "Medicare withheld from the employee at 1.45% (no wage cap)", 82 key: "medicare_withheld_employee", 83 formula: "=ROUND({gross_wages_this_period}*0.0145,2)", 84 }, 85 { 86 label: "Additional Medicare withheld at 0.9% on wages over $200,000 year to date", 87 key: "additional_medicare_withheld", 88 formula: 89 "=ROUND((MAX(0,{ytd_wages_before_this_period}+{gross_wages_this_period}-200000)-MAX(0,{ytd_wages_before_this_period}-200000))*0.009,2)", 90 }, 91 { 92 label: "Total withheld from this paycheck, income tax plus FICA", 93 key: "employee_taxes_withheld_total", 94 formula: 95 "=ROUND({federal_income_tax_withheld}+{ss_withheld_employee}+{medicare_withheld_employee}+{additional_medicare_withheld},2)", 96 }, 97 { 98 label: "Net pay before state income tax and benefit deductions", 99 key: "net_pay_this_period", 100 formula: "=ROUND({gross_wages_this_period}-{employee_taxes_withheld_total},2)", 101 }, 102 ], 103 }, 104 ], 105 }, 106 lang: "en", 107 locale: "en-US", 108 currency: "USD", 109 paid: "", 110 slug: "payroll-tax-spreadsheet", 111 ui: { 112 inputs: "Your numbers", 113 results: "Your result", 114 recalc: "Everything updates as you type.", 115 get: "Get the full calculator", 116 email: "Email me the full version", 117 placeholder: "you@example.com", 118 sent: "Sent. Check your inbox.", 119 share: "Save result image", 120 copy: "Copy link", 121 copied: "Link copied", 122 more: "Full version: all tabs, your own file, works offline.", 123 free: "Free calculator", 124 note: "Nothing is uploaded. This runs in your browser.", 125 dl: "Download my numbers (CSV)", 126 dl_need: "Enter your email above and we will unlock the download.", 127 dl_done: "Downloaded.", 128 }, 129 title: 130 "Payroll Tax Spreadsheet for US Small Employers — FICA, FUTA and State UI Wage-Base Caps per Paycheck", 131 }); 132 document.body.appendChild(s); 133 })(); -
readystack-payroll-tax-spreadsheet/tags/1.0.2/assets/tool-2.js
r3712579 r3713964 1 var PRE={"=MIN({gross_wages_this_period},MAX(0,{social_security_wage_base}-{ytd_wages_before_this_period}))":function(V,FN){return (FN.MIN( V["gross_wages_this_period"] ,FN.MAX(0, V["social_security_wage_base"] - V["ytd_wages_before_this_period"] )));},"=ROUND({ss_taxable_wages}*0.062,2)":function(V,FN){return (FN.ROUND( V["ss_taxable_wages"] *0.062,2));},"=ROUND({gross_wages_this_period}*0.0145,2)":function(V,FN){return (FN.ROUND( V["gross_wages_this_period"] *0.0145,2));},"=ROUND((MAX(0,{ytd_wages_before_this_period}+{gross_wages_this_period}-200000)-MAX(0,{ytd_wages_before_this_period}-200000))*0.009,2)":function(V,FN){return (FN.ROUND((FN.MAX(0, V["ytd_wages_before_this_period"] + V["gross_wages_this_period"] -200000)-FN.MAX(0, V["ytd_wages_before_this_period"] -200000))*0.009,2));},"=ROUND({federal_income_tax_withheld}+{ss_withheld_employee}+{medicare_withheld_employee}+{additional_medicare_withheld},2)":function(V,FN){return (FN.ROUND( V["federal_income_tax_withheld"] + V["ss_withheld_employee"] + V["medicare_withheld_employee"] + V["additional_medicare_withheld"] ,2));},"=ROUND({gross_wages_this_period}-{employee_taxes_withheld_total},2)":function(V,FN){return (FN.ROUND( V["gross_wages_this_period"] - V["employee_taxes_withheld_total"] ,2));},"=ROUND({ss_taxable_wages}*0.062+{gross_wages_this_period}*0.0145,2)":function(V,FN){return (FN.ROUND( V["ss_taxable_wages"] *0.062+ V["gross_wages_this_period"] *0.0145,2));},"=MIN({gross_wages_this_period},MAX(0,{futa_wage_base}-{ytd_wages_before_this_period}))":function(V,FN){return (FN.MIN( V["gross_wages_this_period"] ,FN.MAX(0, V["futa_wage_base"] - V["ytd_wages_before_this_period"] )));},"=ROUND({futa_taxable_wages}*{futa_net_rate},2)":function(V,FN){return (FN.ROUND( V["futa_taxable_wages"] * V["futa_net_rate"] ,2));},"=ROUND(MIN({gross_wages_this_period},MAX(0,{state_ui_wage_base}-{ytd_wages_before_this_period}))*{state_ui_rate},2)":function(V,FN){return (FN.ROUND(FN.MIN( V["gross_wages_this_period"] ,FN.MAX(0, V["state_ui_wage_base"] - V["ytd_wages_before_this_period"] ))* V["state_ui_rate"] ,2));},"=ROUND({federal_income_tax_withheld}+{ss_withheld_employee}+{medicare_withheld_employee}+{additional_medicare_withheld}+{employer_ss_and_medicare_match},2)":function(V,FN){return (FN.ROUND( V["federal_income_tax_withheld"] + V["ss_withheld_employee"] + V["medicare_withheld_employee"] + V["additional_medicare_withheld"] + V["employer_ss_and_medicare_match"] ,2));},"=ROUND({gross_wages_this_period}+{employer_ss_and_medicare_match}+{futa_tax_this_period}+{state_ui_tax_this_period},2)":function(V,FN){return (FN.ROUND( V["gross_wages_this_period"] + V["employer_ss_and_medicare_match"] + V["futa_tax_this_period"] + V["state_ui_tax_this_period"] ,2));}}; 1 var PRE = { 2 "=MIN({gross_wages_this_period},MAX(0,{social_security_wage_base}-{ytd_wages_before_this_period}))": 3 function (V, FN) { 4 return FN.MIN( 5 V["gross_wages_this_period"], 6 FN.MAX(0, V["social_security_wage_base"] - V["ytd_wages_before_this_period"]), 7 ); 8 }, 9 "=ROUND({ss_taxable_wages}*0.062,2)": function (V, FN) { 10 return FN.ROUND(V["ss_taxable_wages"] * 0.062, 2); 11 }, 12 "=ROUND({gross_wages_this_period}*0.0145,2)": function (V, FN) { 13 return FN.ROUND(V["gross_wages_this_period"] * 0.0145, 2); 14 }, 15 "=ROUND((MAX(0,{ytd_wages_before_this_period}+{gross_wages_this_period}-200000)-MAX(0,{ytd_wages_before_this_period}-200000))*0.009,2)": 16 function (V, FN) { 17 return FN.ROUND( 18 (FN.MAX(0, V["ytd_wages_before_this_period"] + V["gross_wages_this_period"] - 200000) - 19 FN.MAX(0, V["ytd_wages_before_this_period"] - 200000)) * 20 0.009, 21 2, 22 ); 23 }, 24 "=ROUND({federal_income_tax_withheld}+{ss_withheld_employee}+{medicare_withheld_employee}+{additional_medicare_withheld},2)": 25 function (V, FN) { 26 return FN.ROUND( 27 V["federal_income_tax_withheld"] + 28 V["ss_withheld_employee"] + 29 V["medicare_withheld_employee"] + 30 V["additional_medicare_withheld"], 31 2, 32 ); 33 }, 34 "=ROUND({gross_wages_this_period}-{employee_taxes_withheld_total},2)": function (V, FN) { 35 return FN.ROUND(V["gross_wages_this_period"] - V["employee_taxes_withheld_total"], 2); 36 }, 37 "=ROUND({ss_taxable_wages}*0.062+{gross_wages_this_period}*0.0145,2)": function (V, FN) { 38 return FN.ROUND(V["ss_taxable_wages"] * 0.062 + V["gross_wages_this_period"] * 0.0145, 2); 39 }, 40 "=MIN({gross_wages_this_period},MAX(0,{futa_wage_base}-{ytd_wages_before_this_period}))": 41 function (V, FN) { 42 return FN.MIN( 43 V["gross_wages_this_period"], 44 FN.MAX(0, V["futa_wage_base"] - V["ytd_wages_before_this_period"]), 45 ); 46 }, 47 "=ROUND({futa_taxable_wages}*{futa_net_rate},2)": function (V, FN) { 48 return FN.ROUND(V["futa_taxable_wages"] * V["futa_net_rate"], 2); 49 }, 50 "=ROUND(MIN({gross_wages_this_period},MAX(0,{state_ui_wage_base}-{ytd_wages_before_this_period}))*{state_ui_rate},2)": 51 function (V, FN) { 52 return FN.ROUND( 53 FN.MIN( 54 V["gross_wages_this_period"], 55 FN.MAX(0, V["state_ui_wage_base"] - V["ytd_wages_before_this_period"]), 56 ) * V["state_ui_rate"], 57 2, 58 ); 59 }, 60 "=ROUND({federal_income_tax_withheld}+{ss_withheld_employee}+{medicare_withheld_employee}+{additional_medicare_withheld}+{employer_ss_and_medicare_match},2)": 61 function (V, FN) { 62 return FN.ROUND( 63 V["federal_income_tax_withheld"] + 64 V["ss_withheld_employee"] + 65 V["medicare_withheld_employee"] + 66 V["additional_medicare_withheld"] + 67 V["employer_ss_and_medicare_match"], 68 2, 69 ); 70 }, 71 "=ROUND({gross_wages_this_period}+{employer_ss_and_medicare_match}+{futa_tax_this_period}+{state_ui_tax_this_period},2)": 72 function (V, FN) { 73 return FN.ROUND( 74 V["gross_wages_this_period"] + 75 V["employer_ss_and_medicare_match"] + 76 V["futa_tax_this_period"] + 77 V["state_ui_tax_this_period"], 78 2, 79 ); 80 }, 81 }; -
readystack-payroll-tax-spreadsheet/tags/1.0.2/assets/tool-3.js
r3712579 r3713964 1 1 var CALC = (function () { 2 function n(x){ x = Number(x); return isFinite(x) ? x : 0; } 3 function ROUND(x, d){ d = n(d); var f = Math.pow(10, d); var v = n(x) * f; 4 var r = (v >= 0) ? Math.floor(v + 0.5) : Math.ceil(v - 0.5); return r / f; } 5 function POWER(a, b){ return Math.pow(n(a), n(b)); } 6 function ABS(a){ return Math.abs(n(a)); } 7 function MIN(){ var a=[].slice.call(arguments).map(n); return a.length?Math.min.apply(null,a):0; } 8 function MAX(){ var a=[].slice.call(arguments).map(n); return a.length?Math.max.apply(null,a):0; } 9 function SUM(){ var s=0; for(var i=0;i<arguments.length;i++) s+=n(arguments[i]); return s; } 10 function IF(c, a, b){ return c ? a : b; } 11 function FLOOR(x, sig){ sig = (arguments.length > 1) ? n(sig) : 1; 12 if (sig === 0) return 0; return Math.floor(n(x) / sig) * sig; } 13 function CEILING(x, sig){ sig = (arguments.length > 1) ? n(sig) : 1; 14 if (sig === 0) return 0; return Math.ceil(n(x) / sig) * sig; } 15 function PMT(rate, nper, pv, fv, type){ 16 rate = n(rate); nper = n(nper); pv = n(pv); fv = n(fv); type = n(type); 2 function n(x) { 3 x = Number(x); 4 return isFinite(x) ? x : 0; 5 } 6 function ROUND(x, d) { 7 d = n(d); 8 var f = Math.pow(10, d); 9 var v = n(x) * f; 10 var r = v >= 0 ? Math.floor(v + 0.5) : Math.ceil(v - 0.5); 11 return r / f; 12 } 13 function POWER(a, b) { 14 return Math.pow(n(a), n(b)); 15 } 16 function ABS(a) { 17 return Math.abs(n(a)); 18 } 19 function MIN() { 20 var a = [].slice.call(arguments).map(n); 21 return a.length ? Math.min.apply(null, a) : 0; 22 } 23 function MAX() { 24 var a = [].slice.call(arguments).map(n); 25 return a.length ? Math.max.apply(null, a) : 0; 26 } 27 function SUM() { 28 var s = 0; 29 for (var i = 0; i < arguments.length; i++) s += n(arguments[i]); 30 return s; 31 } 32 function IF(c, a, b) { 33 return c ? a : b; 34 } 35 function FLOOR(x, sig) { 36 sig = arguments.length > 1 ? n(sig) : 1; 37 if (sig === 0) return 0; 38 return Math.floor(n(x) / sig) * sig; 39 } 40 function CEILING(x, sig) { 41 sig = arguments.length > 1 ? n(sig) : 1; 42 if (sig === 0) return 0; 43 return Math.ceil(n(x) / sig) * sig; 44 } 45 function PMT(rate, nper, pv, fv, type) { 46 rate = n(rate); 47 nper = n(nper); 48 pv = n(pv); 49 fv = n(fv); 50 type = n(type); 17 51 if (nper === 0) return 0; 18 52 if (rate === 0) return -(pv + fv) / nper; 19 53 var p = Math.pow(1 + rate, nper); 20 return -(pv * p + fv) * rate/ ((p - 1) * (1 + rate * type));54 return (-(pv * p + fv) * rate) / ((p - 1) * (1 + rate * type)); 21 55 } 22 var FN = { ROUND:ROUND, POWER:POWER, ABS:ABS, MIN:MIN, MAX:MAX, SUM:SUM, IF:IF, PMT:PMT, 23 FLOOR:FLOOR, CEILING:CEILING }; 56 var FN = { 57 ROUND: ROUND, 58 POWER: POWER, 59 ABS: ABS, 60 MIN: MIN, 61 MAX: MAX, 62 SUM: SUM, 63 IF: IF, 64 PMT: PMT, 65 FLOOR: FLOOR, 66 CEILING: CEILING, 67 }; 24 68 var FNAMES = Object.keys(FN); 25 69 … … 30 74 // 하는 대신 ★주석을 바꾼다 (⛔검사기를 무디게 만드는 것이 s67 의 병이었다). 31 75 // ⇒ ★빌드 때 toExpr 로 식을 뽑아 HTML 에 ★구워 넣고, 브라우저는 ★조회만 한다. 32 function toExpr(formula) {33 var s = String(formula || '').trim();34 if (s.charAt(0) === '=') s = s.slice(1);76 function toExpr(formula) { 77 var s = String(formula || "").trim(); 78 if (s.charAt(0) === "=") s = s.slice(1); 35 79 if (!s) return null; 36 s = s.replace(/\{([A-Za-z0-9_]+)\}/g, function(_, k){ return ' V["' + k + '"] '; }); 37 s = s.replace(/<>/g, '!==').replace(/>=/g, '@GE@').replace(/<=/g, '@LE@'); 38 s = s.replace(/=/g, '===').replace(/@GE@/g, '>=').replace(/@LE@/g, '<='); 39 s = s.replace(/\^/g, '**'); 40 FNAMES.forEach(function(f){ s = s.replace(new RegExp('\\b' + f + '\\s*\\(', 'gi'), 'FN.' + f + '('); }); 41 var probe = s.replace(/V\["[A-Za-z0-9_]+"\]/g, '0').replace(/FN\.[A-Z]+\(/g, '('); 80 s = s.replace(/\{([A-Za-z0-9_]+)\}/g, function (_, k) { 81 return ' V["' + k + '"] '; 82 }); 83 s = s.replace(/<>/g, "!==").replace(/>=/g, "@GE@").replace(/<=/g, "@LE@"); 84 s = s.replace(/=/g, "===").replace(/@GE@/g, ">=").replace(/@LE@/g, "<="); 85 s = s.replace(/\^/g, "**"); 86 FNAMES.forEach(function (f) { 87 s = s.replace(new RegExp("\\b" + f + "\\s*\\(", "gi"), "FN." + f + "("); 88 }); 89 var probe = s.replace(/V\["[A-Za-z0-9_]+"\]/g, "0").replace(/FN\.[A-Z]+\(/g, "("); 42 90 if (!/^[0-9+\-*/%().,\s<>=!&|*]*$/.test(probe)) { 43 throw new Error( 'unsupported token in formula: '+ formula);91 throw new Error("unsupported token in formula: " + formula); 44 92 } 45 93 return s; 46 94 } 47 function compile(formula) {95 function compile(formula) { 48 96 // ★브라우저: 빌드 때 구워넣은 PRE 를 ★조회만 한다 (eval 0). 49 var raw = String(formula || '').trim();97 var raw = String(formula || "").trim(); 50 98 if (!raw) return null; 51 if (typeof PRE !== 'undefined'&& PRE && PRE[raw]) return PRE[raw];52 throw new Error( 'not precompiled: '+ raw);99 if (typeof PRE !== "undefined" && PRE && PRE[raw]) return PRE[raw]; 100 throw new Error("not precompiled: " + raw); 53 101 } 54 102 55 103 // 명세 -> {values, order, rows}. ⛔없는 key 는 0 (xlsx_builder 와 같은 규칙). 56 function run(spec, override) {104 function run(spec, override) { 57 105 var sheets = (spec.sheets_content && spec.sheets_content.sheets) || spec.sheets || []; 58 106 var V = Object.create(null); 59 var order = [], rows = []; 60 var handler = { get: function(t, k){ return (k in t) ? t[k] : 0; } }; 61 var PV = (typeof Proxy !== 'undefined') ? new Proxy(V, handler) : V; 62 sheets.forEach(function(sh){ 107 var order = [], 108 rows = []; 109 var handler = { 110 get: function (t, k) { 111 return k in t ? t[k] : 0; 112 }, 113 }; 114 var PV = typeof Proxy !== "undefined" ? new Proxy(V, handler) : V; 115 sheets.forEach(function (sh) { 63 116 if (sh && sh.inputs && sh.inputs.length) { 64 sh.inputs.forEach(function (it){117 sh.inputs.forEach(function (it) { 65 118 if (!it || !it.key) return; 66 var v = (override && (it.key in override))? override[it.key] : it.value;119 var v = override && it.key in override ? override[it.key] : it.value; 67 120 V[it.key] = n(v); 68 121 }); 69 122 } 70 123 }); 71 sheets.forEach(function (sh){124 sheets.forEach(function (sh) { 72 125 if (!sh || !sh.calc_rows || !sh.calc_rows.length) return; 73 sh.calc_rows.forEach(function (cr){126 sh.calc_rows.forEach(function (cr) { 74 127 if (!cr) return; 75 var val = 0, err = null; 76 try { var f = compile(cr.formula); val = f ? n(f(PV, FN)) : 0; } 77 catch (e) { err = String(e && e.message || e); } 128 var val = 0, 129 err = null; 130 try { 131 var f = compile(cr.formula); 132 val = f ? n(f(PV, FN)) : 0; 133 } catch (e) { 134 err = String((e && e.message) || e); 135 } 78 136 if (cr.key) V[cr.key] = val; 79 var rec = { sheet: sh.name, label: cr.label, key: cr.key || null, 80 format: cr.format || 'number', value: val, error: err }; 81 order.push(rec); rows.push(rec); 137 var rec = { 138 sheet: sh.name, 139 label: cr.label, 140 key: cr.key || null, 141 format: cr.format || "number", 142 value: val, 143 error: err, 144 }; 145 order.push(rec); 146 rows.push(rec); 82 147 }); 83 148 }); … … 86 151 return { run: run, compile: compile, toExpr: toExpr, FN: FN }; 87 152 })(); 88 if (typeof module !== 'undefined'&& module.exports) module.exports = CALC;153 if (typeof module !== "undefined" && module.exports) module.exports = CALC; -
readystack-payroll-tax-spreadsheet/tags/1.0.2/assets/tool-4.js
r3712579 r3713964 1 (function(){ 2 var D=JSON.parse(document.getElementById('calcdata').textContent); 3 var UI=D.ui, LOC=D.locale, CUR=D.currency; 4 function fmt(v,f){ 5 if(!isFinite(v)) v=0; 6 if(f==='currency') return new Intl.NumberFormat(LOC,{style:'currency',currency:CUR,maximumFractionDigits:2}).format(v); 7 if(f==='percent') return new Intl.NumberFormat(LOC,{style:'percent',minimumFractionDigits:2,maximumFractionDigits:2}).format(v); 8 if(f==='integer'||f==='int') return new Intl.NumberFormat(LOC,{maximumFractionDigits:0}).format(v); 9 return new Intl.NumberFormat(LOC,{maximumFractionDigits:4}).format(v); 1 (function () { 2 var D = JSON.parse(document.getElementById("calcdata").textContent); 3 var UI = D.ui, 4 LOC = D.locale, 5 CUR = D.currency; 6 function fmt(v, f) { 7 if (!isFinite(v)) v = 0; 8 if (f === "currency") 9 return new Intl.NumberFormat(LOC, { 10 style: "currency", 11 currency: CUR, 12 maximumFractionDigits: 2, 13 }).format(v); 14 if (f === "percent") 15 return new Intl.NumberFormat(LOC, { 16 style: "percent", 17 minimumFractionDigits: 2, 18 maximumFractionDigits: 2, 19 }).format(v); 20 if (f === "integer" || f === "int") 21 return new Intl.NumberFormat(LOC, { maximumFractionDigits: 0 }).format(v); 22 return new Intl.NumberFormat(LOC, { maximumFractionDigits: 4 }).format(v); 10 23 } 11 var ins=[].slice.call(document.querySelectorAll('input[data-k]')); 12 var outs=[].slice.call(document.querySelectorAll('td.v')); 13 function recalc(){ 14 var ov={}; ins.forEach(function(el){ 15 var n=Number(el.value)||0; ov[el.dataset.k]= el.dataset.pct ? n/100 : n; }); 16 var r=CALC.run(D.spec,ov); 17 var byKey={}, i=0; 18 r.rows.forEach(function(x){ if(x.key) byKey[x.key]=x; }); 19 outs.forEach(function(td){ 24 var ins = [].slice.call(document.querySelectorAll("input[data-k]")); 25 var outs = [].slice.call(document.querySelectorAll("td.v")); 26 function recalc() { 27 var ov = {}; 28 ins.forEach(function (el) { 29 var n = Number(el.value) || 0; 30 ov[el.dataset.k] = el.dataset.pct ? n / 100 : n; 31 }); 32 var r = CALC.run(D.spec, ov); 33 var byKey = {}, 34 i = 0; 35 r.rows.forEach(function (x) { 36 if (x.key) byKey[x.key] = x; 37 }); 38 outs.forEach(function (td) { 20 39 var rec = td.dataset.k ? byKey[td.dataset.k] : r.rows[i]; 21 40 i++; 22 if(!rec){ td.textContent='-'; return; } 23 td.textContent = rec.error ? '-' : fmt(rec.value, td.dataset.f); 41 if (!rec) { 42 td.textContent = "-"; 43 return; 44 } 45 td.textContent = rec.error ? "-" : fmt(rec.value, td.dataset.f); 24 46 }); 25 window.__last =r;47 window.__last = r; 26 48 } 27 ins.forEach(function(el){ el.addEventListener('input',recalc); }); 49 ins.forEach(function (el) { 50 el.addEventListener("input", recalc); 51 }); 28 52 recalc(); 29 53 … … 34 58 // So: the ANSWER stays free, and "the NEXT step" (taking your own numbers away as a file) 35 59 // is what asks for the email (Zeigarnik). Whoever already gave it is never asked again. 36 document.getElementById( 'dl').addEventListener('click',function(){37 var rr =[['label','value']];38 ins.forEach(function (el){39 var lb =(el.closest('label')||{}).textContent||el.dataset.k;60 document.getElementById("dl").addEventListener("click", function () { 61 var rr = [["label", "value"]]; 62 ins.forEach(function (el) { 63 var lb = (el.closest("label") || {}).textContent || el.dataset.k; 40 64 rr.push([String(lb).trim(), el.value]); 41 65 }); 42 ((window.__last &&window.__last.rows)||[]).forEach(function(r){43 rr.push([String(r.label), r.error ?'':String(r.value)]);66 ((window.__last && window.__last.rows) || []).forEach(function (r) { 67 rr.push([String(r.label), r.error ? "" : String(r.value)]); 44 68 }); 45 var csv=rr.map(function(r){ 46 return r.map(function(c){ return '"'+String(c).replace(/"/g,'""')+'"'; }).join(','); 47 }).join('\n'); 48 var bl=new Blob(['\ufeff'+csv],{type:'text/csv;charset=utf-8'}); 49 var ae=document.createElement('a'); 50 ae.href=URL.createObjectURL(bl); ae.download=(D.slug||'result')+'.csv'; ae.click(); 51 var bt=this, tx=bt.textContent; 52 bt.textContent='Downloaded.'; setTimeout(function(){ bt.textContent=tx; },1800); 69 var csv = rr 70 .map(function (r) { 71 return r 72 .map(function (c) { 73 return '"' + String(c).replace(/"/g, '""') + '"'; 74 }) 75 .join(","); 76 }) 77 .join("\n"); 78 var bl = new Blob(["\ufeff" + csv], { type: "text/csv;charset=utf-8" }); 79 var ae = document.createElement("a"); 80 ae.href = URL.createObjectURL(bl); 81 ae.download = (D.slug || "result") + ".csv"; 82 ae.click(); 83 var bt = this, 84 tx = bt.textContent; 85 bt.textContent = "Downloaded."; 86 setTimeout(function () { 87 bt.textContent = tx; 88 }, 1800); 53 89 }); 54 90 55 document.getElementById('sh').addEventListener('click',function(){ 56 var c=document.getElementById('cv'), x=c.getContext('2d'); 57 x.fillStyle='#0e1116'; x.fillRect(0,0,1200,630); 58 x.fillStyle='#fff'; x.font='bold 52px system-ui,sans-serif'; 59 x.fillText(D.title.slice(0,42),64,120); 60 var rws=(window.__last&&window.__last.rows)||[]; var y=230; 61 rws.slice(0,5).forEach(function(r){ 62 x.fillStyle='#9aa4b2'; x.font='28px system-ui,sans-serif'; 63 x.fillText(String(r.label).slice(0,44),64,y); 64 x.fillStyle='#7aa2f7'; x.font='bold 34px system-ui,sans-serif'; 65 x.textAlign='right'; x.fillText(fmt(r.value,r.format),1136,y); x.textAlign='left'; 66 y+=72; 91 document.getElementById("sh").addEventListener("click", function () { 92 var c = document.getElementById("cv"), 93 x = c.getContext("2d"); 94 x.fillStyle = "#0e1116"; 95 x.fillRect(0, 0, 1200, 630); 96 x.fillStyle = "#fff"; 97 x.font = "bold 52px system-ui,sans-serif"; 98 x.fillText(D.title.slice(0, 42), 64, 120); 99 var rws = (window.__last && window.__last.rows) || []; 100 var y = 230; 101 rws.slice(0, 5).forEach(function (r) { 102 x.fillStyle = "#9aa4b2"; 103 x.font = "28px system-ui,sans-serif"; 104 x.fillText(String(r.label).slice(0, 44), 64, y); 105 x.fillStyle = "#7aa2f7"; 106 x.font = "bold 34px system-ui,sans-serif"; 107 x.textAlign = "right"; 108 x.fillText(fmt(r.value, r.format), 1136, y); 109 x.textAlign = "left"; 110 y += 72; 67 111 }); 68 x.fillStyle='#6b7280'; x.font='24px system-ui,sans-serif'; 69 x.fillText(location.host+(D.slug?'/tools/'+D.slug:''),64,590); 70 var a=document.createElement('a'); a.download=(D.slug||'result')+'.png'; 71 a.href=c.toDataURL('image/png'); a.click(); 112 x.fillStyle = "#6b7280"; 113 x.font = "24px system-ui,sans-serif"; 114 x.fillText(location.host + (D.slug ? "/tools/" + D.slug : ""), 64, 590); 115 var a = document.createElement("a"); 116 a.download = (D.slug || "result") + ".png"; 117 a.href = c.toDataURL("image/png"); 118 a.click(); 72 119 }); 73 120 // ★★2026-08-22 s99 (B2) — ★링크 복사. ⛔이게 없으면 ★도메인이 같이 퍼지지 않는다. 74 121 // ★결과 이미지는 ★도메인을 찍어서 나가고, ★링크는 ★그 자리로 되돌아오게 한다. 75 document.getElementById('cp').addEventListener('click',function(){ 76 var b=this, t=b.textContent; 77 var u=location.href.split('#')[0]; 78 function done(){ b.textContent='Link copied'; setTimeout(function(){ b.textContent=t; },1800); } 79 if(navigator.clipboard&&navigator.clipboard.writeText){ 80 navigator.clipboard.writeText(u).then(done,function(){ prompt('',u); }); 81 } else { prompt('',u); } 122 document.getElementById("cp").addEventListener("click", function () { 123 var b = this, 124 t = b.textContent; 125 var u = location.href.split("#")[0]; 126 function done() { 127 b.textContent = "Link copied"; 128 setTimeout(function () { 129 b.textContent = t; 130 }, 1800); 131 } 132 if (navigator.clipboard && navigator.clipboard.writeText) { 133 navigator.clipboard.writeText(u).then(done, function () { 134 prompt("", u); 135 }); 136 } else { 137 prompt("", u); 138 } 82 139 }); 83 140 })(); -
readystack-payroll-tax-spreadsheet/tags/1.0.2/assets/tool.css
r3712579 r3713964 1 .readystack-tool{--bg:#fff;--fg:#111;--mut:#666;--line:#e5e5e5;--acc:#1a56db;--ok:#0f7b3f} 2 @media(prefers-color-scheme:dark){.readystack-tool{--bg:#111;--fg:#eee;--mut:#999;--line:#2a2a2a;--acc:#7aa2f7;--ok:#5fd08a}} 3 .readystack-tool,.readystack-tool *{box-sizing:border-box} 4 .readystack-tool{margin:0;background:var(--bg);color:var(--fg);font:16px/1.55 system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif} 5 .readystack-tool .wrap{max-width:820px;margin:0 auto;padding:24px 18px 64px} 6 .readystack-tool h2{font-size:1.6rem;line-height:1.25;margin:.2em 0 .1em} 7 .readystack-tool .sub{color:var(--mut);margin:0 0 1.4em} 8 .readystack-tool .card{border:1px solid var(--line);border-radius:12px;padding:18px;margin:0 0 18px} 9 .readystack-tool h2{font-size:.85rem;letter-spacing:.08em;text-transform:uppercase;color:var(--mut);margin:0 0 14px} 10 .readystack-tool label{display:flex;justify-content:space-between;align-items:center;gap:14px;padding:7px 0;border-bottom:1px solid var(--line)} 11 .readystack-tool label:last-child{border-bottom:0} 12 .readystack-tool label span{flex:1;font-size:.95rem} 13 .readystack-tool input[type=number]{width:9.5em;padding:8px 10px;border:1px solid var(--line);border-radius:8px;background:transparent;color:var(--fg);font:inherit;text-align:right} 14 .readystack-tool .fld{display:inline-flex;align-items:center;gap:6px} 15 .readystack-tool .fld i{font-style:normal;color:var(--mut);width:1em} 16 .readystack-tool table{width:100%;border-collapse:collapse} 17 .readystack-tool td{padding:8px 0;border-bottom:1px solid var(--line);vertical-align:top} 18 .readystack-tool tr:last-child td{border-bottom:0} 19 .readystack-tool td.l{font-size:.95rem} 20 .readystack-tool td.v{text-align:right;font-variant-numeric:tabular-nums;font-weight:600;white-space:nowrap} 21 .readystack-tool .hint{color:var(--mut);font-size:.85rem;margin:10px 0 0} 22 .readystack-tool .cta{border:1px solid var(--acc);border-radius:12px;padding:18px;margin:22px 0 0} 23 .readystack-tool .cta b{display:block;margin-bottom:6px} 24 .readystack-tool .row{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px} 25 .readystack-tool input[type=email]{flex:1;min-width:200px;padding:10px 12px;border:1px solid var(--line);border-radius:8px;background:transparent;color:var(--fg);font:inherit} 26 .readystack-tool button{padding:10px 16px;border:0;border-radius:8px;background:var(--acc);color:#fff;font:inherit;font-weight:600;cursor:pointer} 27 .readystack-tool button.ghost{background:transparent;color:var(--acc);border:1px solid var(--acc)} 28 .readystack-tool a.buy{display:inline-block;margin-top:10px;color:var(--acc);font-weight:600} 29 .readystack-tool .ok{color:var(--ok);font-size:.9rem;margin-top:8px} 30 .readystack-tool canvas{display:none} 1 .readystack-tool { 2 --bg: #fff; 3 --fg: #111; 4 --mut: #666; 5 --line: #e5e5e5; 6 --acc: #1a56db; 7 --ok: #0f7b3f; 8 } 9 @media (prefers-color-scheme: dark) { 10 .readystack-tool { 11 --bg: #111; 12 --fg: #eee; 13 --mut: #999; 14 --line: #2a2a2a; 15 --acc: #7aa2f7; 16 --ok: #5fd08a; 17 } 18 } 19 .readystack-tool, 20 .readystack-tool * { 21 box-sizing: border-box; 22 } 23 .readystack-tool { 24 margin: 0; 25 background: var(--bg); 26 color: var(--fg); 27 font: 28 16px/1.55 system-ui, 29 -apple-system, 30 "Segoe UI", 31 Roboto, 32 "Helvetica Neue", 33 sans-serif; 34 } 35 .readystack-tool .wrap { 36 max-width: 820px; 37 margin: 0 auto; 38 padding: 24px 18px 64px; 39 } 40 .readystack-tool h2 { 41 font-size: 1.6rem; 42 line-height: 1.25; 43 margin: 0.2em 0 0.1em; 44 } 45 .readystack-tool .sub { 46 color: var(--mut); 47 margin: 0 0 1.4em; 48 } 49 .readystack-tool .card { 50 border: 1px solid var(--line); 51 border-radius: 12px; 52 padding: 18px; 53 margin: 0 0 18px; 54 } 55 .readystack-tool h2 { 56 font-size: 0.85rem; 57 letter-spacing: 0.08em; 58 text-transform: uppercase; 59 color: var(--mut); 60 margin: 0 0 14px; 61 } 62 .readystack-tool label { 63 display: flex; 64 justify-content: space-between; 65 align-items: center; 66 gap: 14px; 67 padding: 7px 0; 68 border-bottom: 1px solid var(--line); 69 } 70 .readystack-tool label:last-child { 71 border-bottom: 0; 72 } 73 .readystack-tool label span { 74 flex: 1; 75 font-size: 0.95rem; 76 } 77 .readystack-tool input[type="number"] { 78 width: 9.5em; 79 padding: 8px 10px; 80 border: 1px solid var(--line); 81 border-radius: 8px; 82 background: transparent; 83 color: var(--fg); 84 font: inherit; 85 text-align: right; 86 } 87 .readystack-tool .fld { 88 display: inline-flex; 89 align-items: center; 90 gap: 6px; 91 } 92 .readystack-tool .fld i { 93 font-style: normal; 94 color: var(--mut); 95 width: 1em; 96 } 97 .readystack-tool table { 98 width: 100%; 99 border-collapse: collapse; 100 } 101 .readystack-tool td { 102 padding: 8px 0; 103 border-bottom: 1px solid var(--line); 104 vertical-align: top; 105 } 106 .readystack-tool tr:last-child td { 107 border-bottom: 0; 108 } 109 .readystack-tool td.l { 110 font-size: 0.95rem; 111 } 112 .readystack-tool td.v { 113 text-align: right; 114 font-variant-numeric: tabular-nums; 115 font-weight: 600; 116 white-space: nowrap; 117 } 118 .readystack-tool .hint { 119 color: var(--mut); 120 font-size: 0.85rem; 121 margin: 10px 0 0; 122 } 123 .readystack-tool .cta { 124 border: 1px solid var(--acc); 125 border-radius: 12px; 126 padding: 18px; 127 margin: 22px 0 0; 128 } 129 .readystack-tool .cta b { 130 display: block; 131 margin-bottom: 6px; 132 } 133 .readystack-tool .row { 134 display: flex; 135 gap: 8px; 136 flex-wrap: wrap; 137 margin-top: 12px; 138 } 139 .readystack-tool input[type="email"] { 140 flex: 1; 141 min-width: 200px; 142 padding: 10px 12px; 143 border: 1px solid var(--line); 144 border-radius: 8px; 145 background: transparent; 146 color: var(--fg); 147 font: inherit; 148 } 149 .readystack-tool button { 150 padding: 10px 16px; 151 border: 0; 152 border-radius: 8px; 153 background: var(--acc); 154 color: #fff; 155 font: inherit; 156 font-weight: 600; 157 cursor: pointer; 158 } 159 .readystack-tool button.ghost { 160 background: transparent; 161 color: var(--acc); 162 border: 1px solid var(--acc); 163 } 164 .readystack-tool a.buy { 165 display: inline-block; 166 margin-top: 10px; 167 color: var(--acc); 168 font-weight: 600; 169 } 170 .readystack-tool .ok { 171 color: var(--ok); 172 font-size: 0.9rem; 173 margin-top: 8px; 174 } 175 .readystack-tool canvas { 176 display: none; 177 } -
readystack-payroll-tax-spreadsheet/tags/1.0.2/readme.txt
r3712579 r3713964 5 5 Tested up to: 7.1 6 6 Requires PHP: 7.4 7 Stable tag: 1.0. 17 Stable tag: 1.0.2 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 29 29 The tool runs in the browser of whoever opens the page. The plugin makes no external requests, sets no cookies, adds no tracking and stores nothing in your database. It has no settings screen. 30 30 31 = Source code = 32 33 The JavaScript and CSS files in the plugin's assets folder are the complete, human-readable source. There is no build step: nothing is compiled, bundled or minified, so what you read is what runs. 34 31 35 == Installation == 32 36 … … 47 51 == Changelog == 48 52 53 = 1.0.2 = 54 * JavaScript and CSS ship as formatted, human-readable source; the readme says where the source is. 55 49 56 = 1.0.1 = 50 57 * The tool output is escaped, its styles are scoped to the tool and its scripts are enqueued; the readme explains how to use it. -
readystack-payroll-tax-spreadsheet/tags/1.0.2/readystack-payroll-tax-spreadsheet.php
r3712579 r3713964 3 3 * Plugin Name: ReadyStack Payroll Tax Spreadsheet 4 4 * Description: Deposit short and the IRS adds 2% to 15% of the shortfall under IRC § 6656. 5 * Version: 1.0. 15 * Version: 1.0.2 6 6 * Requires at least: 6.0 7 7 * Requires PHP: 7.4 … … 23 23 */ 24 24 function readystack_payroll_tax_spreadsheet_register_assets() { 25 wp_register_style( 'readystack-payroll-tax-spreadsheet', plugins_url( 'assets/tool.css', __FILE__ ), array(), '1.0. 1' );26 wp_register_script( 'readystack-payroll-tax-spreadsheet-1', plugins_url( 'assets/tool-1.js', __FILE__ ), array(), '1.0. 1', true );27 wp_register_script( 'readystack-payroll-tax-spreadsheet-2', plugins_url( 'assets/tool-2.js', __FILE__ ), array( 'readystack-payroll-tax-spreadsheet-1' ), '1.0. 1', true );28 wp_register_script( 'readystack-payroll-tax-spreadsheet-3', plugins_url( 'assets/tool-3.js', __FILE__ ), array( 'readystack-payroll-tax-spreadsheet-2' ), '1.0. 1', true );29 wp_register_script( 'readystack-payroll-tax-spreadsheet-4', plugins_url( 'assets/tool-4.js', __FILE__ ), array( 'readystack-payroll-tax-spreadsheet-3' ), '1.0. 1', true );25 wp_register_style( 'readystack-payroll-tax-spreadsheet', plugins_url( 'assets/tool.css', __FILE__ ), array(), '1.0.2' ); 26 wp_register_script( 'readystack-payroll-tax-spreadsheet-1', plugins_url( 'assets/tool-1.js', __FILE__ ), array(), '1.0.2', true ); 27 wp_register_script( 'readystack-payroll-tax-spreadsheet-2', plugins_url( 'assets/tool-2.js', __FILE__ ), array( 'readystack-payroll-tax-spreadsheet-1' ), '1.0.2', true ); 28 wp_register_script( 'readystack-payroll-tax-spreadsheet-3', plugins_url( 'assets/tool-3.js', __FILE__ ), array( 'readystack-payroll-tax-spreadsheet-2' ), '1.0.2', true ); 29 wp_register_script( 'readystack-payroll-tax-spreadsheet-4', plugins_url( 'assets/tool-4.js', __FILE__ ), array( 'readystack-payroll-tax-spreadsheet-3' ), '1.0.2', true ); 30 30 } 31 31 add_action( 'wp_enqueue_scripts', 'readystack_payroll_tax_spreadsheet_register_assets' ); -
readystack-payroll-tax-spreadsheet/trunk/assets/tool-1.js
r3712579 r3713964 1 (function(){var s=document.createElement("script");s.type="application/json";s.id="calcdata";s.textContent="{\"spec\": {\"sheets\": [{\"name\": \"Inputs - Your Payroll Numbers\", \"purpose\": \"Type your own eight numbers here; both calc sheets recalculate. A free online paycheck calculator cannot carry year-to-date wages from one run to the next, so it never knows that Social Security has already stopped for this employee — that is the whole reason this file exists. Rates you must confirm yourself are inputs, not guesses: the Social Security wage base is set by the SSA each October and the default shown is the 2025 figure of 176,100, so replace it with the figure for the year you are running. The $7,000 FUTA base is statutory. Your state UI rate and state UI taxable wage base come from your state agency's annual notice and differ in every state. Excel: open the file. Google Sheets: File, Import, Upload, Replace spreadsheet.\", \"inputs\": [{\"label\": \"Gross wages this pay period, one employee\", \"key\": \"gross_wages_this_period\", \"value\": 3000, \"format\": \"currency\"}, {\"label\": \"Wages already paid to this employee this year, before this period\", \"key\": \"ytd_wages_before_this_period\", \"value\": 6000, \"format\": \"currency\"}, {\"label\": \"Federal income tax withheld this period (from IRS Publication 15-T)\", \"key\": \"federal_income_tax_withheld\", \"value\": 316, \"format\": \"currency\"}, {\"label\": \"Social Security wage base for your tax year (SSA notice; 2025 figure shown)\", \"key\": \"social_security_wage_base\", \"value\": 176100, \"format\": \"currency\"}, {\"label\": \"FUTA wage base per employee per year (statutory)\", \"key\": \"futa_wage_base\", \"value\": 7000, \"format\": \"currency\"}, {\"label\": \"FUTA net rate after the 5.4% state credit (use 6.0% in a credit-reduction state)\", \"key\": \"futa_net_rate\", \"value\": 0.006, \"format\": \"percent\"}, {\"label\": \"Your state UI taxable wage base (from your state agency notice)\", \"key\": \"state_ui_wage_base\", \"value\": 7000, \"format\": \"currency\"}, {\"label\": \"Your assigned state UI rate for this year (from your state agency notice)\", \"key\": \"state_ui_rate\", \"value\": 0.034, \"format\": \"percent\"}]}, {\"name\": \"1. This Paycheck (Employee)\", \"purpose\": \"One question, answered completely: what comes out of this paycheck. Social Security stops at the wage base, Medicare never stops, and the extra 0.9% starts only after $200,000 of wages in the calendar year — employers withhold that 0.9% at $200,000 regardless of the employee's filing status, and do not match it (IRS Publication 15). Charge 6.2% on wages above the base and you over-withhold: the employee recovers it on their 1040, but your Form 941 no longer ties out and the correction lands on you. Net pay here is before state income tax and any benefit deductions.\", \"calc_rows\": [{\"label\": \"Wages subject to Social Security this period (capped at the wage base)\", \"key\": \"ss_taxable_wages\", \"formula\": \"=MIN({gross_wages_this_period},MAX(0,{social_security_wage_base}-{ytd_wages_before_this_period}))\"}, {\"label\": \"Social Security withheld from the employee at 6.2%\", \"key\": \"ss_withheld_employee\", \"formula\": \"=ROUND({ss_taxable_wages}*0.062,2)\"}, {\"label\": \"Medicare withheld from the employee at 1.45% (no wage cap)\", \"key\": \"medicare_withheld_employee\", \"formula\": \"=ROUND({gross_wages_this_period}*0.0145,2)\"}, {\"label\": \"Additional Medicare withheld at 0.9% on wages over $200,000 year to date\", \"key\": \"additional_medicare_withheld\", \"formula\": \"=ROUND((MAX(0,{ytd_wages_before_this_period}+{gross_wages_this_period}-200000)-MAX(0,{ytd_wages_before_this_period}-200000))*0.009,2)\"}, {\"label\": \"Total withheld from this paycheck, income tax plus FICA\", \"key\": \"employee_taxes_withheld_total\", \"formula\": \"=ROUND({federal_income_tax_withheld}+{ss_withheld_employee}+{medicare_withheld_employee}+{additional_medicare_withheld},2)\"}, {\"label\": \"Net pay before state income tax and benefit deductions\", \"key\": \"net_pay_this_period\", \"formula\": \"=ROUND({gross_wages_this_period}-{employee_taxes_withheld_total},2)\"}]}]}, \"lang\": \"en\", \"locale\": \"en-US\", \"currency\": \"USD\", \"paid\": \"\", \"slug\": \"payroll-tax-spreadsheet\", \"ui\": {\"inputs\": \"Your numbers\", \"results\": \"Your result\", \"recalc\": \"Everything updates as you type.\", \"get\": \"Get the full calculator\", \"email\": \"Email me the full version\", \"placeholder\": \"you@example.com\", \"sent\": \"Sent. Check your inbox.\", \"share\": \"Save result image\", \"copy\": \"Copy link\", \"copied\": \"Link copied\", \"more\": \"Full version: all tabs, your own file, works offline.\", \"free\": \"Free calculator\", \"note\": \"Nothing is uploaded. This runs in your browser.\", \"dl\": \"Download my numbers (CSV)\", \"dl_need\": \"Enter your email above and we will unlock the download.\", \"dl_done\": \"Downloaded.\"}, \"title\": \"Payroll Tax Spreadsheet for US Small Employers — FICA, FUTA and State UI Wage-Base Caps per Paycheck\"}";document.body.appendChild(s);})(); 1 (function () { 2 var s = document.createElement("script"); 3 s.type = "application/json"; 4 s.id = "calcdata"; 5 s.textContent = JSON.stringify({ 6 spec: { 7 sheets: [ 8 { 9 name: "Inputs - Your Payroll Numbers", 10 purpose: 11 "Type your own eight numbers here; both calc sheets recalculate. A free online paycheck calculator cannot carry year-to-date wages from one run to the next, so it never knows that Social Security has already stopped for this employee — that is the whole reason this file exists. Rates you must confirm yourself are inputs, not guesses: the Social Security wage base is set by the SSA each October and the default shown is the 2025 figure of 176,100, so replace it with the figure for the year you are running. The $7,000 FUTA base is statutory. Your state UI rate and state UI taxable wage base come from your state agency's annual notice and differ in every state. Excel: open the file. Google Sheets: File, Import, Upload, Replace spreadsheet.", 12 inputs: [ 13 { 14 label: "Gross wages this pay period, one employee", 15 key: "gross_wages_this_period", 16 value: 3000, 17 format: "currency", 18 }, 19 { 20 label: "Wages already paid to this employee this year, before this period", 21 key: "ytd_wages_before_this_period", 22 value: 6000, 23 format: "currency", 24 }, 25 { 26 label: "Federal income tax withheld this period (from IRS Publication 15-T)", 27 key: "federal_income_tax_withheld", 28 value: 316, 29 format: "currency", 30 }, 31 { 32 label: "Social Security wage base for your tax year (SSA notice; 2025 figure shown)", 33 key: "social_security_wage_base", 34 value: 176100, 35 format: "currency", 36 }, 37 { 38 label: "FUTA wage base per employee per year (statutory)", 39 key: "futa_wage_base", 40 value: 7000, 41 format: "currency", 42 }, 43 { 44 label: 45 "FUTA net rate after the 5.4% state credit (use 6.0% in a credit-reduction state)", 46 key: "futa_net_rate", 47 value: 0.006, 48 format: "percent", 49 }, 50 { 51 label: "Your state UI taxable wage base (from your state agency notice)", 52 key: "state_ui_wage_base", 53 value: 7000, 54 format: "currency", 55 }, 56 { 57 label: "Your assigned state UI rate for this year (from your state agency notice)", 58 key: "state_ui_rate", 59 value: 0.034, 60 format: "percent", 61 }, 62 ], 63 }, 64 { 65 name: "1. This Paycheck (Employee)", 66 purpose: 67 "One question, answered completely: what comes out of this paycheck. Social Security stops at the wage base, Medicare never stops, and the extra 0.9% starts only after $200,000 of wages in the calendar year — employers withhold that 0.9% at $200,000 regardless of the employee's filing status, and do not match it (IRS Publication 15). Charge 6.2% on wages above the base and you over-withhold: the employee recovers it on their 1040, but your Form 941 no longer ties out and the correction lands on you. Net pay here is before state income tax and any benefit deductions.", 68 calc_rows: [ 69 { 70 label: "Wages subject to Social Security this period (capped at the wage base)", 71 key: "ss_taxable_wages", 72 formula: 73 "=MIN({gross_wages_this_period},MAX(0,{social_security_wage_base}-{ytd_wages_before_this_period}))", 74 }, 75 { 76 label: "Social Security withheld from the employee at 6.2%", 77 key: "ss_withheld_employee", 78 formula: "=ROUND({ss_taxable_wages}*0.062,2)", 79 }, 80 { 81 label: "Medicare withheld from the employee at 1.45% (no wage cap)", 82 key: "medicare_withheld_employee", 83 formula: "=ROUND({gross_wages_this_period}*0.0145,2)", 84 }, 85 { 86 label: "Additional Medicare withheld at 0.9% on wages over $200,000 year to date", 87 key: "additional_medicare_withheld", 88 formula: 89 "=ROUND((MAX(0,{ytd_wages_before_this_period}+{gross_wages_this_period}-200000)-MAX(0,{ytd_wages_before_this_period}-200000))*0.009,2)", 90 }, 91 { 92 label: "Total withheld from this paycheck, income tax plus FICA", 93 key: "employee_taxes_withheld_total", 94 formula: 95 "=ROUND({federal_income_tax_withheld}+{ss_withheld_employee}+{medicare_withheld_employee}+{additional_medicare_withheld},2)", 96 }, 97 { 98 label: "Net pay before state income tax and benefit deductions", 99 key: "net_pay_this_period", 100 formula: "=ROUND({gross_wages_this_period}-{employee_taxes_withheld_total},2)", 101 }, 102 ], 103 }, 104 ], 105 }, 106 lang: "en", 107 locale: "en-US", 108 currency: "USD", 109 paid: "", 110 slug: "payroll-tax-spreadsheet", 111 ui: { 112 inputs: "Your numbers", 113 results: "Your result", 114 recalc: "Everything updates as you type.", 115 get: "Get the full calculator", 116 email: "Email me the full version", 117 placeholder: "you@example.com", 118 sent: "Sent. Check your inbox.", 119 share: "Save result image", 120 copy: "Copy link", 121 copied: "Link copied", 122 more: "Full version: all tabs, your own file, works offline.", 123 free: "Free calculator", 124 note: "Nothing is uploaded. This runs in your browser.", 125 dl: "Download my numbers (CSV)", 126 dl_need: "Enter your email above and we will unlock the download.", 127 dl_done: "Downloaded.", 128 }, 129 title: 130 "Payroll Tax Spreadsheet for US Small Employers — FICA, FUTA and State UI Wage-Base Caps per Paycheck", 131 }); 132 document.body.appendChild(s); 133 })(); -
readystack-payroll-tax-spreadsheet/trunk/assets/tool-2.js
r3712579 r3713964 1 var PRE={"=MIN({gross_wages_this_period},MAX(0,{social_security_wage_base}-{ytd_wages_before_this_period}))":function(V,FN){return (FN.MIN( V["gross_wages_this_period"] ,FN.MAX(0, V["social_security_wage_base"] - V["ytd_wages_before_this_period"] )));},"=ROUND({ss_taxable_wages}*0.062,2)":function(V,FN){return (FN.ROUND( V["ss_taxable_wages"] *0.062,2));},"=ROUND({gross_wages_this_period}*0.0145,2)":function(V,FN){return (FN.ROUND( V["gross_wages_this_period"] *0.0145,2));},"=ROUND((MAX(0,{ytd_wages_before_this_period}+{gross_wages_this_period}-200000)-MAX(0,{ytd_wages_before_this_period}-200000))*0.009,2)":function(V,FN){return (FN.ROUND((FN.MAX(0, V["ytd_wages_before_this_period"] + V["gross_wages_this_period"] -200000)-FN.MAX(0, V["ytd_wages_before_this_period"] -200000))*0.009,2));},"=ROUND({federal_income_tax_withheld}+{ss_withheld_employee}+{medicare_withheld_employee}+{additional_medicare_withheld},2)":function(V,FN){return (FN.ROUND( V["federal_income_tax_withheld"] + V["ss_withheld_employee"] + V["medicare_withheld_employee"] + V["additional_medicare_withheld"] ,2));},"=ROUND({gross_wages_this_period}-{employee_taxes_withheld_total},2)":function(V,FN){return (FN.ROUND( V["gross_wages_this_period"] - V["employee_taxes_withheld_total"] ,2));},"=ROUND({ss_taxable_wages}*0.062+{gross_wages_this_period}*0.0145,2)":function(V,FN){return (FN.ROUND( V["ss_taxable_wages"] *0.062+ V["gross_wages_this_period"] *0.0145,2));},"=MIN({gross_wages_this_period},MAX(0,{futa_wage_base}-{ytd_wages_before_this_period}))":function(V,FN){return (FN.MIN( V["gross_wages_this_period"] ,FN.MAX(0, V["futa_wage_base"] - V["ytd_wages_before_this_period"] )));},"=ROUND({futa_taxable_wages}*{futa_net_rate},2)":function(V,FN){return (FN.ROUND( V["futa_taxable_wages"] * V["futa_net_rate"] ,2));},"=ROUND(MIN({gross_wages_this_period},MAX(0,{state_ui_wage_base}-{ytd_wages_before_this_period}))*{state_ui_rate},2)":function(V,FN){return (FN.ROUND(FN.MIN( V["gross_wages_this_period"] ,FN.MAX(0, V["state_ui_wage_base"] - V["ytd_wages_before_this_period"] ))* V["state_ui_rate"] ,2));},"=ROUND({federal_income_tax_withheld}+{ss_withheld_employee}+{medicare_withheld_employee}+{additional_medicare_withheld}+{employer_ss_and_medicare_match},2)":function(V,FN){return (FN.ROUND( V["federal_income_tax_withheld"] + V["ss_withheld_employee"] + V["medicare_withheld_employee"] + V["additional_medicare_withheld"] + V["employer_ss_and_medicare_match"] ,2));},"=ROUND({gross_wages_this_period}+{employer_ss_and_medicare_match}+{futa_tax_this_period}+{state_ui_tax_this_period},2)":function(V,FN){return (FN.ROUND( V["gross_wages_this_period"] + V["employer_ss_and_medicare_match"] + V["futa_tax_this_period"] + V["state_ui_tax_this_period"] ,2));}}; 1 var PRE = { 2 "=MIN({gross_wages_this_period},MAX(0,{social_security_wage_base}-{ytd_wages_before_this_period}))": 3 function (V, FN) { 4 return FN.MIN( 5 V["gross_wages_this_period"], 6 FN.MAX(0, V["social_security_wage_base"] - V["ytd_wages_before_this_period"]), 7 ); 8 }, 9 "=ROUND({ss_taxable_wages}*0.062,2)": function (V, FN) { 10 return FN.ROUND(V["ss_taxable_wages"] * 0.062, 2); 11 }, 12 "=ROUND({gross_wages_this_period}*0.0145,2)": function (V, FN) { 13 return FN.ROUND(V["gross_wages_this_period"] * 0.0145, 2); 14 }, 15 "=ROUND((MAX(0,{ytd_wages_before_this_period}+{gross_wages_this_period}-200000)-MAX(0,{ytd_wages_before_this_period}-200000))*0.009,2)": 16 function (V, FN) { 17 return FN.ROUND( 18 (FN.MAX(0, V["ytd_wages_before_this_period"] + V["gross_wages_this_period"] - 200000) - 19 FN.MAX(0, V["ytd_wages_before_this_period"] - 200000)) * 20 0.009, 21 2, 22 ); 23 }, 24 "=ROUND({federal_income_tax_withheld}+{ss_withheld_employee}+{medicare_withheld_employee}+{additional_medicare_withheld},2)": 25 function (V, FN) { 26 return FN.ROUND( 27 V["federal_income_tax_withheld"] + 28 V["ss_withheld_employee"] + 29 V["medicare_withheld_employee"] + 30 V["additional_medicare_withheld"], 31 2, 32 ); 33 }, 34 "=ROUND({gross_wages_this_period}-{employee_taxes_withheld_total},2)": function (V, FN) { 35 return FN.ROUND(V["gross_wages_this_period"] - V["employee_taxes_withheld_total"], 2); 36 }, 37 "=ROUND({ss_taxable_wages}*0.062+{gross_wages_this_period}*0.0145,2)": function (V, FN) { 38 return FN.ROUND(V["ss_taxable_wages"] * 0.062 + V["gross_wages_this_period"] * 0.0145, 2); 39 }, 40 "=MIN({gross_wages_this_period},MAX(0,{futa_wage_base}-{ytd_wages_before_this_period}))": 41 function (V, FN) { 42 return FN.MIN( 43 V["gross_wages_this_period"], 44 FN.MAX(0, V["futa_wage_base"] - V["ytd_wages_before_this_period"]), 45 ); 46 }, 47 "=ROUND({futa_taxable_wages}*{futa_net_rate},2)": function (V, FN) { 48 return FN.ROUND(V["futa_taxable_wages"] * V["futa_net_rate"], 2); 49 }, 50 "=ROUND(MIN({gross_wages_this_period},MAX(0,{state_ui_wage_base}-{ytd_wages_before_this_period}))*{state_ui_rate},2)": 51 function (V, FN) { 52 return FN.ROUND( 53 FN.MIN( 54 V["gross_wages_this_period"], 55 FN.MAX(0, V["state_ui_wage_base"] - V["ytd_wages_before_this_period"]), 56 ) * V["state_ui_rate"], 57 2, 58 ); 59 }, 60 "=ROUND({federal_income_tax_withheld}+{ss_withheld_employee}+{medicare_withheld_employee}+{additional_medicare_withheld}+{employer_ss_and_medicare_match},2)": 61 function (V, FN) { 62 return FN.ROUND( 63 V["federal_income_tax_withheld"] + 64 V["ss_withheld_employee"] + 65 V["medicare_withheld_employee"] + 66 V["additional_medicare_withheld"] + 67 V["employer_ss_and_medicare_match"], 68 2, 69 ); 70 }, 71 "=ROUND({gross_wages_this_period}+{employer_ss_and_medicare_match}+{futa_tax_this_period}+{state_ui_tax_this_period},2)": 72 function (V, FN) { 73 return FN.ROUND( 74 V["gross_wages_this_period"] + 75 V["employer_ss_and_medicare_match"] + 76 V["futa_tax_this_period"] + 77 V["state_ui_tax_this_period"], 78 2, 79 ); 80 }, 81 }; -
readystack-payroll-tax-spreadsheet/trunk/assets/tool-3.js
r3712579 r3713964 1 1 var CALC = (function () { 2 function n(x){ x = Number(x); return isFinite(x) ? x : 0; } 3 function ROUND(x, d){ d = n(d); var f = Math.pow(10, d); var v = n(x) * f; 4 var r = (v >= 0) ? Math.floor(v + 0.5) : Math.ceil(v - 0.5); return r / f; } 5 function POWER(a, b){ return Math.pow(n(a), n(b)); } 6 function ABS(a){ return Math.abs(n(a)); } 7 function MIN(){ var a=[].slice.call(arguments).map(n); return a.length?Math.min.apply(null,a):0; } 8 function MAX(){ var a=[].slice.call(arguments).map(n); return a.length?Math.max.apply(null,a):0; } 9 function SUM(){ var s=0; for(var i=0;i<arguments.length;i++) s+=n(arguments[i]); return s; } 10 function IF(c, a, b){ return c ? a : b; } 11 function FLOOR(x, sig){ sig = (arguments.length > 1) ? n(sig) : 1; 12 if (sig === 0) return 0; return Math.floor(n(x) / sig) * sig; } 13 function CEILING(x, sig){ sig = (arguments.length > 1) ? n(sig) : 1; 14 if (sig === 0) return 0; return Math.ceil(n(x) / sig) * sig; } 15 function PMT(rate, nper, pv, fv, type){ 16 rate = n(rate); nper = n(nper); pv = n(pv); fv = n(fv); type = n(type); 2 function n(x) { 3 x = Number(x); 4 return isFinite(x) ? x : 0; 5 } 6 function ROUND(x, d) { 7 d = n(d); 8 var f = Math.pow(10, d); 9 var v = n(x) * f; 10 var r = v >= 0 ? Math.floor(v + 0.5) : Math.ceil(v - 0.5); 11 return r / f; 12 } 13 function POWER(a, b) { 14 return Math.pow(n(a), n(b)); 15 } 16 function ABS(a) { 17 return Math.abs(n(a)); 18 } 19 function MIN() { 20 var a = [].slice.call(arguments).map(n); 21 return a.length ? Math.min.apply(null, a) : 0; 22 } 23 function MAX() { 24 var a = [].slice.call(arguments).map(n); 25 return a.length ? Math.max.apply(null, a) : 0; 26 } 27 function SUM() { 28 var s = 0; 29 for (var i = 0; i < arguments.length; i++) s += n(arguments[i]); 30 return s; 31 } 32 function IF(c, a, b) { 33 return c ? a : b; 34 } 35 function FLOOR(x, sig) { 36 sig = arguments.length > 1 ? n(sig) : 1; 37 if (sig === 0) return 0; 38 return Math.floor(n(x) / sig) * sig; 39 } 40 function CEILING(x, sig) { 41 sig = arguments.length > 1 ? n(sig) : 1; 42 if (sig === 0) return 0; 43 return Math.ceil(n(x) / sig) * sig; 44 } 45 function PMT(rate, nper, pv, fv, type) { 46 rate = n(rate); 47 nper = n(nper); 48 pv = n(pv); 49 fv = n(fv); 50 type = n(type); 17 51 if (nper === 0) return 0; 18 52 if (rate === 0) return -(pv + fv) / nper; 19 53 var p = Math.pow(1 + rate, nper); 20 return -(pv * p + fv) * rate/ ((p - 1) * (1 + rate * type));54 return (-(pv * p + fv) * rate) / ((p - 1) * (1 + rate * type)); 21 55 } 22 var FN = { ROUND:ROUND, POWER:POWER, ABS:ABS, MIN:MIN, MAX:MAX, SUM:SUM, IF:IF, PMT:PMT, 23 FLOOR:FLOOR, CEILING:CEILING }; 56 var FN = { 57 ROUND: ROUND, 58 POWER: POWER, 59 ABS: ABS, 60 MIN: MIN, 61 MAX: MAX, 62 SUM: SUM, 63 IF: IF, 64 PMT: PMT, 65 FLOOR: FLOOR, 66 CEILING: CEILING, 67 }; 24 68 var FNAMES = Object.keys(FN); 25 69 … … 30 74 // 하는 대신 ★주석을 바꾼다 (⛔검사기를 무디게 만드는 것이 s67 의 병이었다). 31 75 // ⇒ ★빌드 때 toExpr 로 식을 뽑아 HTML 에 ★구워 넣고, 브라우저는 ★조회만 한다. 32 function toExpr(formula) {33 var s = String(formula || '').trim();34 if (s.charAt(0) === '=') s = s.slice(1);76 function toExpr(formula) { 77 var s = String(formula || "").trim(); 78 if (s.charAt(0) === "=") s = s.slice(1); 35 79 if (!s) return null; 36 s = s.replace(/\{([A-Za-z0-9_]+)\}/g, function(_, k){ return ' V["' + k + '"] '; }); 37 s = s.replace(/<>/g, '!==').replace(/>=/g, '@GE@').replace(/<=/g, '@LE@'); 38 s = s.replace(/=/g, '===').replace(/@GE@/g, '>=').replace(/@LE@/g, '<='); 39 s = s.replace(/\^/g, '**'); 40 FNAMES.forEach(function(f){ s = s.replace(new RegExp('\\b' + f + '\\s*\\(', 'gi'), 'FN.' + f + '('); }); 41 var probe = s.replace(/V\["[A-Za-z0-9_]+"\]/g, '0').replace(/FN\.[A-Z]+\(/g, '('); 80 s = s.replace(/\{([A-Za-z0-9_]+)\}/g, function (_, k) { 81 return ' V["' + k + '"] '; 82 }); 83 s = s.replace(/<>/g, "!==").replace(/>=/g, "@GE@").replace(/<=/g, "@LE@"); 84 s = s.replace(/=/g, "===").replace(/@GE@/g, ">=").replace(/@LE@/g, "<="); 85 s = s.replace(/\^/g, "**"); 86 FNAMES.forEach(function (f) { 87 s = s.replace(new RegExp("\\b" + f + "\\s*\\(", "gi"), "FN." + f + "("); 88 }); 89 var probe = s.replace(/V\["[A-Za-z0-9_]+"\]/g, "0").replace(/FN\.[A-Z]+\(/g, "("); 42 90 if (!/^[0-9+\-*/%().,\s<>=!&|*]*$/.test(probe)) { 43 throw new Error( 'unsupported token in formula: '+ formula);91 throw new Error("unsupported token in formula: " + formula); 44 92 } 45 93 return s; 46 94 } 47 function compile(formula) {95 function compile(formula) { 48 96 // ★브라우저: 빌드 때 구워넣은 PRE 를 ★조회만 한다 (eval 0). 49 var raw = String(formula || '').trim();97 var raw = String(formula || "").trim(); 50 98 if (!raw) return null; 51 if (typeof PRE !== 'undefined'&& PRE && PRE[raw]) return PRE[raw];52 throw new Error( 'not precompiled: '+ raw);99 if (typeof PRE !== "undefined" && PRE && PRE[raw]) return PRE[raw]; 100 throw new Error("not precompiled: " + raw); 53 101 } 54 102 55 103 // 명세 -> {values, order, rows}. ⛔없는 key 는 0 (xlsx_builder 와 같은 규칙). 56 function run(spec, override) {104 function run(spec, override) { 57 105 var sheets = (spec.sheets_content && spec.sheets_content.sheets) || spec.sheets || []; 58 106 var V = Object.create(null); 59 var order = [], rows = []; 60 var handler = { get: function(t, k){ return (k in t) ? t[k] : 0; } }; 61 var PV = (typeof Proxy !== 'undefined') ? new Proxy(V, handler) : V; 62 sheets.forEach(function(sh){ 107 var order = [], 108 rows = []; 109 var handler = { 110 get: function (t, k) { 111 return k in t ? t[k] : 0; 112 }, 113 }; 114 var PV = typeof Proxy !== "undefined" ? new Proxy(V, handler) : V; 115 sheets.forEach(function (sh) { 63 116 if (sh && sh.inputs && sh.inputs.length) { 64 sh.inputs.forEach(function (it){117 sh.inputs.forEach(function (it) { 65 118 if (!it || !it.key) return; 66 var v = (override && (it.key in override))? override[it.key] : it.value;119 var v = override && it.key in override ? override[it.key] : it.value; 67 120 V[it.key] = n(v); 68 121 }); 69 122 } 70 123 }); 71 sheets.forEach(function (sh){124 sheets.forEach(function (sh) { 72 125 if (!sh || !sh.calc_rows || !sh.calc_rows.length) return; 73 sh.calc_rows.forEach(function (cr){126 sh.calc_rows.forEach(function (cr) { 74 127 if (!cr) return; 75 var val = 0, err = null; 76 try { var f = compile(cr.formula); val = f ? n(f(PV, FN)) : 0; } 77 catch (e) { err = String(e && e.message || e); } 128 var val = 0, 129 err = null; 130 try { 131 var f = compile(cr.formula); 132 val = f ? n(f(PV, FN)) : 0; 133 } catch (e) { 134 err = String((e && e.message) || e); 135 } 78 136 if (cr.key) V[cr.key] = val; 79 var rec = { sheet: sh.name, label: cr.label, key: cr.key || null, 80 format: cr.format || 'number', value: val, error: err }; 81 order.push(rec); rows.push(rec); 137 var rec = { 138 sheet: sh.name, 139 label: cr.label, 140 key: cr.key || null, 141 format: cr.format || "number", 142 value: val, 143 error: err, 144 }; 145 order.push(rec); 146 rows.push(rec); 82 147 }); 83 148 }); … … 86 151 return { run: run, compile: compile, toExpr: toExpr, FN: FN }; 87 152 })(); 88 if (typeof module !== 'undefined'&& module.exports) module.exports = CALC;153 if (typeof module !== "undefined" && module.exports) module.exports = CALC; -
readystack-payroll-tax-spreadsheet/trunk/assets/tool-4.js
r3712579 r3713964 1 (function(){ 2 var D=JSON.parse(document.getElementById('calcdata').textContent); 3 var UI=D.ui, LOC=D.locale, CUR=D.currency; 4 function fmt(v,f){ 5 if(!isFinite(v)) v=0; 6 if(f==='currency') return new Intl.NumberFormat(LOC,{style:'currency',currency:CUR,maximumFractionDigits:2}).format(v); 7 if(f==='percent') return new Intl.NumberFormat(LOC,{style:'percent',minimumFractionDigits:2,maximumFractionDigits:2}).format(v); 8 if(f==='integer'||f==='int') return new Intl.NumberFormat(LOC,{maximumFractionDigits:0}).format(v); 9 return new Intl.NumberFormat(LOC,{maximumFractionDigits:4}).format(v); 1 (function () { 2 var D = JSON.parse(document.getElementById("calcdata").textContent); 3 var UI = D.ui, 4 LOC = D.locale, 5 CUR = D.currency; 6 function fmt(v, f) { 7 if (!isFinite(v)) v = 0; 8 if (f === "currency") 9 return new Intl.NumberFormat(LOC, { 10 style: "currency", 11 currency: CUR, 12 maximumFractionDigits: 2, 13 }).format(v); 14 if (f === "percent") 15 return new Intl.NumberFormat(LOC, { 16 style: "percent", 17 minimumFractionDigits: 2, 18 maximumFractionDigits: 2, 19 }).format(v); 20 if (f === "integer" || f === "int") 21 return new Intl.NumberFormat(LOC, { maximumFractionDigits: 0 }).format(v); 22 return new Intl.NumberFormat(LOC, { maximumFractionDigits: 4 }).format(v); 10 23 } 11 var ins=[].slice.call(document.querySelectorAll('input[data-k]')); 12 var outs=[].slice.call(document.querySelectorAll('td.v')); 13 function recalc(){ 14 var ov={}; ins.forEach(function(el){ 15 var n=Number(el.value)||0; ov[el.dataset.k]= el.dataset.pct ? n/100 : n; }); 16 var r=CALC.run(D.spec,ov); 17 var byKey={}, i=0; 18 r.rows.forEach(function(x){ if(x.key) byKey[x.key]=x; }); 19 outs.forEach(function(td){ 24 var ins = [].slice.call(document.querySelectorAll("input[data-k]")); 25 var outs = [].slice.call(document.querySelectorAll("td.v")); 26 function recalc() { 27 var ov = {}; 28 ins.forEach(function (el) { 29 var n = Number(el.value) || 0; 30 ov[el.dataset.k] = el.dataset.pct ? n / 100 : n; 31 }); 32 var r = CALC.run(D.spec, ov); 33 var byKey = {}, 34 i = 0; 35 r.rows.forEach(function (x) { 36 if (x.key) byKey[x.key] = x; 37 }); 38 outs.forEach(function (td) { 20 39 var rec = td.dataset.k ? byKey[td.dataset.k] : r.rows[i]; 21 40 i++; 22 if(!rec){ td.textContent='-'; return; } 23 td.textContent = rec.error ? '-' : fmt(rec.value, td.dataset.f); 41 if (!rec) { 42 td.textContent = "-"; 43 return; 44 } 45 td.textContent = rec.error ? "-" : fmt(rec.value, td.dataset.f); 24 46 }); 25 window.__last =r;47 window.__last = r; 26 48 } 27 ins.forEach(function(el){ el.addEventListener('input',recalc); }); 49 ins.forEach(function (el) { 50 el.addEventListener("input", recalc); 51 }); 28 52 recalc(); 29 53 … … 34 58 // So: the ANSWER stays free, and "the NEXT step" (taking your own numbers away as a file) 35 59 // is what asks for the email (Zeigarnik). Whoever already gave it is never asked again. 36 document.getElementById( 'dl').addEventListener('click',function(){37 var rr =[['label','value']];38 ins.forEach(function (el){39 var lb =(el.closest('label')||{}).textContent||el.dataset.k;60 document.getElementById("dl").addEventListener("click", function () { 61 var rr = [["label", "value"]]; 62 ins.forEach(function (el) { 63 var lb = (el.closest("label") || {}).textContent || el.dataset.k; 40 64 rr.push([String(lb).trim(), el.value]); 41 65 }); 42 ((window.__last &&window.__last.rows)||[]).forEach(function(r){43 rr.push([String(r.label), r.error ?'':String(r.value)]);66 ((window.__last && window.__last.rows) || []).forEach(function (r) { 67 rr.push([String(r.label), r.error ? "" : String(r.value)]); 44 68 }); 45 var csv=rr.map(function(r){ 46 return r.map(function(c){ return '"'+String(c).replace(/"/g,'""')+'"'; }).join(','); 47 }).join('\n'); 48 var bl=new Blob(['\ufeff'+csv],{type:'text/csv;charset=utf-8'}); 49 var ae=document.createElement('a'); 50 ae.href=URL.createObjectURL(bl); ae.download=(D.slug||'result')+'.csv'; ae.click(); 51 var bt=this, tx=bt.textContent; 52 bt.textContent='Downloaded.'; setTimeout(function(){ bt.textContent=tx; },1800); 69 var csv = rr 70 .map(function (r) { 71 return r 72 .map(function (c) { 73 return '"' + String(c).replace(/"/g, '""') + '"'; 74 }) 75 .join(","); 76 }) 77 .join("\n"); 78 var bl = new Blob(["\ufeff" + csv], { type: "text/csv;charset=utf-8" }); 79 var ae = document.createElement("a"); 80 ae.href = URL.createObjectURL(bl); 81 ae.download = (D.slug || "result") + ".csv"; 82 ae.click(); 83 var bt = this, 84 tx = bt.textContent; 85 bt.textContent = "Downloaded."; 86 setTimeout(function () { 87 bt.textContent = tx; 88 }, 1800); 53 89 }); 54 90 55 document.getElementById('sh').addEventListener('click',function(){ 56 var c=document.getElementById('cv'), x=c.getContext('2d'); 57 x.fillStyle='#0e1116'; x.fillRect(0,0,1200,630); 58 x.fillStyle='#fff'; x.font='bold 52px system-ui,sans-serif'; 59 x.fillText(D.title.slice(0,42),64,120); 60 var rws=(window.__last&&window.__last.rows)||[]; var y=230; 61 rws.slice(0,5).forEach(function(r){ 62 x.fillStyle='#9aa4b2'; x.font='28px system-ui,sans-serif'; 63 x.fillText(String(r.label).slice(0,44),64,y); 64 x.fillStyle='#7aa2f7'; x.font='bold 34px system-ui,sans-serif'; 65 x.textAlign='right'; x.fillText(fmt(r.value,r.format),1136,y); x.textAlign='left'; 66 y+=72; 91 document.getElementById("sh").addEventListener("click", function () { 92 var c = document.getElementById("cv"), 93 x = c.getContext("2d"); 94 x.fillStyle = "#0e1116"; 95 x.fillRect(0, 0, 1200, 630); 96 x.fillStyle = "#fff"; 97 x.font = "bold 52px system-ui,sans-serif"; 98 x.fillText(D.title.slice(0, 42), 64, 120); 99 var rws = (window.__last && window.__last.rows) || []; 100 var y = 230; 101 rws.slice(0, 5).forEach(function (r) { 102 x.fillStyle = "#9aa4b2"; 103 x.font = "28px system-ui,sans-serif"; 104 x.fillText(String(r.label).slice(0, 44), 64, y); 105 x.fillStyle = "#7aa2f7"; 106 x.font = "bold 34px system-ui,sans-serif"; 107 x.textAlign = "right"; 108 x.fillText(fmt(r.value, r.format), 1136, y); 109 x.textAlign = "left"; 110 y += 72; 67 111 }); 68 x.fillStyle='#6b7280'; x.font='24px system-ui,sans-serif'; 69 x.fillText(location.host+(D.slug?'/tools/'+D.slug:''),64,590); 70 var a=document.createElement('a'); a.download=(D.slug||'result')+'.png'; 71 a.href=c.toDataURL('image/png'); a.click(); 112 x.fillStyle = "#6b7280"; 113 x.font = "24px system-ui,sans-serif"; 114 x.fillText(location.host + (D.slug ? "/tools/" + D.slug : ""), 64, 590); 115 var a = document.createElement("a"); 116 a.download = (D.slug || "result") + ".png"; 117 a.href = c.toDataURL("image/png"); 118 a.click(); 72 119 }); 73 120 // ★★2026-08-22 s99 (B2) — ★링크 복사. ⛔이게 없으면 ★도메인이 같이 퍼지지 않는다. 74 121 // ★결과 이미지는 ★도메인을 찍어서 나가고, ★링크는 ★그 자리로 되돌아오게 한다. 75 document.getElementById('cp').addEventListener('click',function(){ 76 var b=this, t=b.textContent; 77 var u=location.href.split('#')[0]; 78 function done(){ b.textContent='Link copied'; setTimeout(function(){ b.textContent=t; },1800); } 79 if(navigator.clipboard&&navigator.clipboard.writeText){ 80 navigator.clipboard.writeText(u).then(done,function(){ prompt('',u); }); 81 } else { prompt('',u); } 122 document.getElementById("cp").addEventListener("click", function () { 123 var b = this, 124 t = b.textContent; 125 var u = location.href.split("#")[0]; 126 function done() { 127 b.textContent = "Link copied"; 128 setTimeout(function () { 129 b.textContent = t; 130 }, 1800); 131 } 132 if (navigator.clipboard && navigator.clipboard.writeText) { 133 navigator.clipboard.writeText(u).then(done, function () { 134 prompt("", u); 135 }); 136 } else { 137 prompt("", u); 138 } 82 139 }); 83 140 })(); -
readystack-payroll-tax-spreadsheet/trunk/assets/tool.css
r3712579 r3713964 1 .readystack-tool{--bg:#fff;--fg:#111;--mut:#666;--line:#e5e5e5;--acc:#1a56db;--ok:#0f7b3f} 2 @media(prefers-color-scheme:dark){.readystack-tool{--bg:#111;--fg:#eee;--mut:#999;--line:#2a2a2a;--acc:#7aa2f7;--ok:#5fd08a}} 3 .readystack-tool,.readystack-tool *{box-sizing:border-box} 4 .readystack-tool{margin:0;background:var(--bg);color:var(--fg);font:16px/1.55 system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif} 5 .readystack-tool .wrap{max-width:820px;margin:0 auto;padding:24px 18px 64px} 6 .readystack-tool h2{font-size:1.6rem;line-height:1.25;margin:.2em 0 .1em} 7 .readystack-tool .sub{color:var(--mut);margin:0 0 1.4em} 8 .readystack-tool .card{border:1px solid var(--line);border-radius:12px;padding:18px;margin:0 0 18px} 9 .readystack-tool h2{font-size:.85rem;letter-spacing:.08em;text-transform:uppercase;color:var(--mut);margin:0 0 14px} 10 .readystack-tool label{display:flex;justify-content:space-between;align-items:center;gap:14px;padding:7px 0;border-bottom:1px solid var(--line)} 11 .readystack-tool label:last-child{border-bottom:0} 12 .readystack-tool label span{flex:1;font-size:.95rem} 13 .readystack-tool input[type=number]{width:9.5em;padding:8px 10px;border:1px solid var(--line);border-radius:8px;background:transparent;color:var(--fg);font:inherit;text-align:right} 14 .readystack-tool .fld{display:inline-flex;align-items:center;gap:6px} 15 .readystack-tool .fld i{font-style:normal;color:var(--mut);width:1em} 16 .readystack-tool table{width:100%;border-collapse:collapse} 17 .readystack-tool td{padding:8px 0;border-bottom:1px solid var(--line);vertical-align:top} 18 .readystack-tool tr:last-child td{border-bottom:0} 19 .readystack-tool td.l{font-size:.95rem} 20 .readystack-tool td.v{text-align:right;font-variant-numeric:tabular-nums;font-weight:600;white-space:nowrap} 21 .readystack-tool .hint{color:var(--mut);font-size:.85rem;margin:10px 0 0} 22 .readystack-tool .cta{border:1px solid var(--acc);border-radius:12px;padding:18px;margin:22px 0 0} 23 .readystack-tool .cta b{display:block;margin-bottom:6px} 24 .readystack-tool .row{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px} 25 .readystack-tool input[type=email]{flex:1;min-width:200px;padding:10px 12px;border:1px solid var(--line);border-radius:8px;background:transparent;color:var(--fg);font:inherit} 26 .readystack-tool button{padding:10px 16px;border:0;border-radius:8px;background:var(--acc);color:#fff;font:inherit;font-weight:600;cursor:pointer} 27 .readystack-tool button.ghost{background:transparent;color:var(--acc);border:1px solid var(--acc)} 28 .readystack-tool a.buy{display:inline-block;margin-top:10px;color:var(--acc);font-weight:600} 29 .readystack-tool .ok{color:var(--ok);font-size:.9rem;margin-top:8px} 30 .readystack-tool canvas{display:none} 1 .readystack-tool { 2 --bg: #fff; 3 --fg: #111; 4 --mut: #666; 5 --line: #e5e5e5; 6 --acc: #1a56db; 7 --ok: #0f7b3f; 8 } 9 @media (prefers-color-scheme: dark) { 10 .readystack-tool { 11 --bg: #111; 12 --fg: #eee; 13 --mut: #999; 14 --line: #2a2a2a; 15 --acc: #7aa2f7; 16 --ok: #5fd08a; 17 } 18 } 19 .readystack-tool, 20 .readystack-tool * { 21 box-sizing: border-box; 22 } 23 .readystack-tool { 24 margin: 0; 25 background: var(--bg); 26 color: var(--fg); 27 font: 28 16px/1.55 system-ui, 29 -apple-system, 30 "Segoe UI", 31 Roboto, 32 "Helvetica Neue", 33 sans-serif; 34 } 35 .readystack-tool .wrap { 36 max-width: 820px; 37 margin: 0 auto; 38 padding: 24px 18px 64px; 39 } 40 .readystack-tool h2 { 41 font-size: 1.6rem; 42 line-height: 1.25; 43 margin: 0.2em 0 0.1em; 44 } 45 .readystack-tool .sub { 46 color: var(--mut); 47 margin: 0 0 1.4em; 48 } 49 .readystack-tool .card { 50 border: 1px solid var(--line); 51 border-radius: 12px; 52 padding: 18px; 53 margin: 0 0 18px; 54 } 55 .readystack-tool h2 { 56 font-size: 0.85rem; 57 letter-spacing: 0.08em; 58 text-transform: uppercase; 59 color: var(--mut); 60 margin: 0 0 14px; 61 } 62 .readystack-tool label { 63 display: flex; 64 justify-content: space-between; 65 align-items: center; 66 gap: 14px; 67 padding: 7px 0; 68 border-bottom: 1px solid var(--line); 69 } 70 .readystack-tool label:last-child { 71 border-bottom: 0; 72 } 73 .readystack-tool label span { 74 flex: 1; 75 font-size: 0.95rem; 76 } 77 .readystack-tool input[type="number"] { 78 width: 9.5em; 79 padding: 8px 10px; 80 border: 1px solid var(--line); 81 border-radius: 8px; 82 background: transparent; 83 color: var(--fg); 84 font: inherit; 85 text-align: right; 86 } 87 .readystack-tool .fld { 88 display: inline-flex; 89 align-items: center; 90 gap: 6px; 91 } 92 .readystack-tool .fld i { 93 font-style: normal; 94 color: var(--mut); 95 width: 1em; 96 } 97 .readystack-tool table { 98 width: 100%; 99 border-collapse: collapse; 100 } 101 .readystack-tool td { 102 padding: 8px 0; 103 border-bottom: 1px solid var(--line); 104 vertical-align: top; 105 } 106 .readystack-tool tr:last-child td { 107 border-bottom: 0; 108 } 109 .readystack-tool td.l { 110 font-size: 0.95rem; 111 } 112 .readystack-tool td.v { 113 text-align: right; 114 font-variant-numeric: tabular-nums; 115 font-weight: 600; 116 white-space: nowrap; 117 } 118 .readystack-tool .hint { 119 color: var(--mut); 120 font-size: 0.85rem; 121 margin: 10px 0 0; 122 } 123 .readystack-tool .cta { 124 border: 1px solid var(--acc); 125 border-radius: 12px; 126 padding: 18px; 127 margin: 22px 0 0; 128 } 129 .readystack-tool .cta b { 130 display: block; 131 margin-bottom: 6px; 132 } 133 .readystack-tool .row { 134 display: flex; 135 gap: 8px; 136 flex-wrap: wrap; 137 margin-top: 12px; 138 } 139 .readystack-tool input[type="email"] { 140 flex: 1; 141 min-width: 200px; 142 padding: 10px 12px; 143 border: 1px solid var(--line); 144 border-radius: 8px; 145 background: transparent; 146 color: var(--fg); 147 font: inherit; 148 } 149 .readystack-tool button { 150 padding: 10px 16px; 151 border: 0; 152 border-radius: 8px; 153 background: var(--acc); 154 color: #fff; 155 font: inherit; 156 font-weight: 600; 157 cursor: pointer; 158 } 159 .readystack-tool button.ghost { 160 background: transparent; 161 color: var(--acc); 162 border: 1px solid var(--acc); 163 } 164 .readystack-tool a.buy { 165 display: inline-block; 166 margin-top: 10px; 167 color: var(--acc); 168 font-weight: 600; 169 } 170 .readystack-tool .ok { 171 color: var(--ok); 172 font-size: 0.9rem; 173 margin-top: 8px; 174 } 175 .readystack-tool canvas { 176 display: none; 177 } -
readystack-payroll-tax-spreadsheet/trunk/readme.txt
r3712579 r3713964 5 5 Tested up to: 7.1 6 6 Requires PHP: 7.4 7 Stable tag: 1.0. 17 Stable tag: 1.0.2 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 29 29 The tool runs in the browser of whoever opens the page. The plugin makes no external requests, sets no cookies, adds no tracking and stores nothing in your database. It has no settings screen. 30 30 31 = Source code = 32 33 The JavaScript and CSS files in the plugin's assets folder are the complete, human-readable source. There is no build step: nothing is compiled, bundled or minified, so what you read is what runs. 34 31 35 == Installation == 32 36 … … 47 51 == Changelog == 48 52 53 = 1.0.2 = 54 * JavaScript and CSS ship as formatted, human-readable source; the readme says where the source is. 55 49 56 = 1.0.1 = 50 57 * The tool output is escaped, its styles are scoped to the tool and its scripts are enqueued; the readme explains how to use it. -
readystack-payroll-tax-spreadsheet/trunk/readystack-payroll-tax-spreadsheet.php
r3712579 r3713964 3 3 * Plugin Name: ReadyStack Payroll Tax Spreadsheet 4 4 * Description: Deposit short and the IRS adds 2% to 15% of the shortfall under IRC § 6656. 5 * Version: 1.0. 15 * Version: 1.0.2 6 6 * Requires at least: 6.0 7 7 * Requires PHP: 7.4 … … 23 23 */ 24 24 function readystack_payroll_tax_spreadsheet_register_assets() { 25 wp_register_style( 'readystack-payroll-tax-spreadsheet', plugins_url( 'assets/tool.css', __FILE__ ), array(), '1.0. 1' );26 wp_register_script( 'readystack-payroll-tax-spreadsheet-1', plugins_url( 'assets/tool-1.js', __FILE__ ), array(), '1.0. 1', true );27 wp_register_script( 'readystack-payroll-tax-spreadsheet-2', plugins_url( 'assets/tool-2.js', __FILE__ ), array( 'readystack-payroll-tax-spreadsheet-1' ), '1.0. 1', true );28 wp_register_script( 'readystack-payroll-tax-spreadsheet-3', plugins_url( 'assets/tool-3.js', __FILE__ ), array( 'readystack-payroll-tax-spreadsheet-2' ), '1.0. 1', true );29 wp_register_script( 'readystack-payroll-tax-spreadsheet-4', plugins_url( 'assets/tool-4.js', __FILE__ ), array( 'readystack-payroll-tax-spreadsheet-3' ), '1.0. 1', true );25 wp_register_style( 'readystack-payroll-tax-spreadsheet', plugins_url( 'assets/tool.css', __FILE__ ), array(), '1.0.2' ); 26 wp_register_script( 'readystack-payroll-tax-spreadsheet-1', plugins_url( 'assets/tool-1.js', __FILE__ ), array(), '1.0.2', true ); 27 wp_register_script( 'readystack-payroll-tax-spreadsheet-2', plugins_url( 'assets/tool-2.js', __FILE__ ), array( 'readystack-payroll-tax-spreadsheet-1' ), '1.0.2', true ); 28 wp_register_script( 'readystack-payroll-tax-spreadsheet-3', plugins_url( 'assets/tool-3.js', __FILE__ ), array( 'readystack-payroll-tax-spreadsheet-2' ), '1.0.2', true ); 29 wp_register_script( 'readystack-payroll-tax-spreadsheet-4', plugins_url( 'assets/tool-4.js', __FILE__ ), array( 'readystack-payroll-tax-spreadsheet-3' ), '1.0.2', true ); 30 30 } 31 31 add_action( 'wp_enqueue_scripts', 'readystack_payroll_tax_spreadsheet_register_assets' );
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)