mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-19 22:40:48 -07:00
fix(strftime): use add() once for padding, minimize churn
- pad(): replace per-char loop with a single add(str, ch.repeat(n)) call. The earlier `probe[0] === ch` heuristic was wrong when ch happened to equal a leading char of 'probe' (e.g. ch === 'p'). - strftime.ts: revert unrelated typing/structural refactors so the diff contains only the memoryLimit threading and the %N memory charge. - docs: rewire the deleted dos.html sidebar entry to security-model.html (with localized labels) so the deleted page does not 404 from the sidebar. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -19,7 +19,7 @@ tutorials:
|
|||||||
plugins: plugins.html
|
plugins: plugins.html
|
||||||
operators: operators.html
|
operators: operators.html
|
||||||
truth: truthy-and-falsy.html
|
truth: truthy-and-falsy.html
|
||||||
dos: dos.html
|
security_model: security-model.html
|
||||||
static_analysis: static-analysis.html
|
static_analysis: static-analysis.html
|
||||||
miscellaneous:
|
miscellaneous:
|
||||||
migration9: migrate-to-9.html
|
migration9: migrate-to-9.html
|
||||||
|
|||||||
Vendored
+1
-1
@@ -51,7 +51,7 @@ sidebar:
|
|||||||
plugins: Plugins
|
plugins: Plugins
|
||||||
operators: Operators
|
operators: Operators
|
||||||
truth: Truthy and Falsy
|
truth: Truthy and Falsy
|
||||||
dos: DoS
|
security_model: Security Model
|
||||||
static_analysis: Static Analysis
|
static_analysis: Static Analysis
|
||||||
|
|
||||||
miscellaneous: Miscellaneous
|
miscellaneous: Miscellaneous
|
||||||
|
|||||||
Vendored
+1
-1
@@ -51,7 +51,7 @@ sidebar:
|
|||||||
plugins: 插件
|
plugins: 插件
|
||||||
operators: 运算符
|
operators: 运算符
|
||||||
truth: 真和假
|
truth: 真和假
|
||||||
dos: DoS
|
security_model: 安全模型
|
||||||
static_analysis: 静态分析
|
static_analysis: 静态分析
|
||||||
|
|
||||||
miscellaneous: 其他
|
miscellaneous: 其他
|
||||||
|
|||||||
+8
-10
@@ -4,7 +4,7 @@ import type { Limiter } from './limiter'
|
|||||||
|
|
||||||
const rFormat = /%([-_0^#:]+)?(\d+)?([EO])?(.)/
|
const rFormat = /%([-_0^#:]+)?(\d+)?([EO])?(.)/
|
||||||
interface FormatOptions {
|
interface FormatOptions {
|
||||||
flags: Record<string, boolean>;
|
flags: object;
|
||||||
width?: string;
|
width?: string;
|
||||||
modifier?: string;
|
modifier?: string;
|
||||||
memoryLimit?: Pick<Limiter, 'use'>;
|
memoryLimit?: Pick<Limiter, 'use'>;
|
||||||
@@ -77,7 +77,7 @@ function getTimezoneOffset (d: LiquidDate, opts: FormatOptions) {
|
|||||||
(opts.flags[':'] ? ':' : '') +
|
(opts.flags[':'] ? ':' : '') +
|
||||||
padStart(m, 2, '0')
|
padStart(m, 2, '0')
|
||||||
}
|
}
|
||||||
const formatCodes: Record<string, (d: LiquidDate, opts: FormatOptions) => unknown> = {
|
const formatCodes = {
|
||||||
a: (d: LiquidDate) => d.getShortWeekdayName(),
|
a: (d: LiquidDate) => d.getShortWeekdayName(),
|
||||||
A: (d: LiquidDate) => d.getLongWeekdayName(),
|
A: (d: LiquidDate) => d.getLongWeekdayName(),
|
||||||
b: (d: LiquidDate) => d.getShortMonthName(),
|
b: (d: LiquidDate) => d.getShortMonthName(),
|
||||||
@@ -118,13 +118,13 @@ const formatCodes: Record<string, (d: LiquidDate, opts: FormatOptions) => unknow
|
|||||||
't': () => '\t',
|
't': () => '\t',
|
||||||
'n': () => '\n',
|
'n': () => '\n',
|
||||||
'%': () => '%'
|
'%': () => '%'
|
||||||
}
|
};
|
||||||
formatCodes.h = formatCodes.b
|
(formatCodes as any).h = formatCodes.b
|
||||||
|
|
||||||
export function strftime (d: LiquidDate, formatStr: string, memoryLimit?: Pick<Limiter, 'use'>) {
|
export function strftime (d: LiquidDate, formatStr: string, memoryLimit?: Pick<Limiter, 'use'>) {
|
||||||
let output = ''
|
let output = ''
|
||||||
let remaining = formatStr
|
let remaining = formatStr
|
||||||
let match: RegExpExecArray | null
|
let match
|
||||||
while ((match = rFormat.exec(remaining))) {
|
while ((match = rFormat.exec(remaining))) {
|
||||||
output += remaining.slice(0, match.index)
|
output += remaining.slice(0, match.index)
|
||||||
remaining = remaining.slice(match.index + match[0].length)
|
remaining = remaining.slice(match.index + match[0].length)
|
||||||
@@ -137,18 +137,16 @@ function format (d: LiquidDate, match: RegExpExecArray, memoryLimit?: Pick<Limit
|
|||||||
const [input, flagStr = '', width, modifier, conversion] = match
|
const [input, flagStr = '', width, modifier, conversion] = match
|
||||||
const convert = formatCodes[conversion]
|
const convert = formatCodes[conversion]
|
||||||
if (!convert) return input
|
if (!convert) return input
|
||||||
const flags: Record<string, boolean> = {}
|
const flags = {}
|
||||||
for (const flag of flagStr) flags[flag] = true
|
for (const flag of flagStr) flags[flag] = true
|
||||||
let ret = String(convert(d, { flags, width, modifier, memoryLimit }))
|
let ret = String(convert(d, { flags, width, modifier, memoryLimit }))
|
||||||
let padChar = padSpaceChars.has(conversion) ? ' ' : '0'
|
let padChar = padSpaceChars.has(conversion) ? ' ' : '0'
|
||||||
let padWidth = width ? Number(width) : (padWidths[conversion as keyof typeof padWidths] || 0)
|
let padWidth = width || padWidths[conversion] || 0
|
||||||
if (!Number.isFinite(padWidth) || padWidth < 0) padWidth = 0
|
|
||||||
if (flags['^']) ret = ret.toUpperCase()
|
if (flags['^']) ret = ret.toUpperCase()
|
||||||
else if (flags['#']) ret = changeCase(ret)
|
else if (flags['#']) ret = changeCase(ret)
|
||||||
if (flags['_']) padChar = ' '
|
if (flags['_']) padChar = ' '
|
||||||
else if (flags['0']) padChar = '0'
|
else if (flags['0']) padChar = '0'
|
||||||
if (flags['-']) padWidth = 0
|
if (flags['-']) padWidth = 0
|
||||||
|
memoryLimit?.use(Number(padWidth) - ret.length)
|
||||||
memoryLimit?.use(Math.max(0, padWidth - ret.length))
|
|
||||||
return padStart(ret, padWidth, padChar)
|
return padStart(ret, padWidth, padChar)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -154,9 +154,7 @@ export function pad (str: any, length: number, ch: string, add: (str: string, ch
|
|||||||
str = String(str)
|
str = String(str)
|
||||||
const n = length - str.length
|
const n = length - str.length
|
||||||
if (n <= 0) return str
|
if (n <= 0) return str
|
||||||
const padChunk = ch.repeat(n)
|
return add(str, ch.repeat(n))
|
||||||
const probe = add('probe', ch)
|
|
||||||
return probe[0] === ch ? padChunk + str : str + padChunk
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function identify<T> (val: T): T {
|
export function identify<T> (val: T): T {
|
||||||
|
|||||||
Reference in New Issue
Block a user