Skip to content

Commit

Permalink
feat(tags): helpful array functions: unique, zip, sorted, groupby
Browse files Browse the repository at this point in the history
  • Loading branch information
stdword committed Feb 19, 2024
1 parent aae442c commit e7b24ec
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 6 deletions.
78 changes: 76 additions & 2 deletions docs/reference__syntax.md
Expand Up @@ -156,8 +156,12 @@ But there are the special `out` & `outn` functions to output info within ` ``{..
<!-- div:right-panel -->
<!-- tabs:start -->
#### ***Template***
- ` ``{ for (const i of [1, 2, 3]) out(i) }`` `
- ` ``{ for (const i of [1, 2, 3]) outn(i) }`` `
- ```javascript
``{ for (const i of [1, 2, 3]) out(i) }``
```
- ```javascript
``{ for (const i of [1, 2, 3]) outn(i) }``
```

#### ***Rendered***
- 123
Expand All @@ -167,8 +171,78 @@ But there are the special `out` & `outn` functions to output info within ` ``{..

<!-- tabs:end -->


<!-- div:left-panel -->
Also the `Array` type extended with helpful functions:
- `Array.zip`
- `Array.unique`
- `Array.sorted`
- `Array.groupby`

<!-- div:right-panel -->
<!-- tabs:start -->
#### ***Template***
- ```javascript
``JSON.stringify(Array.zip([1, 2, 3], ['a', 'b']))``
```
- ```javascript
``[1, 2, 2, 3, 2, 1, 1].unique()``
```

#### ***Rendered***
- [[1,"a"],[2,"b"]]
- 1,2,3

<!-- tabs:end -->

<!-- panels:end -->

<!-- tabs:start -->
#### ***Template***
- ```javascript
var items = [
{ type: "vegetables", quantity: 5 },
{ type: "fruit", quantity: 1 },
{ type: "meat", quantity: 23 },
{ type: "fruit", quantity: 5 },
{ type: "meat", quantity: 22 },
]
```
- ```javascript
``items.sorted((x) => [x.type, x.quantity]).map(JSON.stringify).join('\n')``
```
- ```javascript
``JSON.stringify(items.groupby((x) => x.type), null, 4)``
```

#### ***Rendered***
- ```javascript
// .sorted
{"type": "fruit", "quantity": 1 }
{"type": "fruit", "quantity": 5 }
{"type": "meat", "quantity": 22 }
{"type": "meat", "quantity": 23 }
{"type": "vegetables", "quantity": 5 }
```
- ```javascript
// .groupby
{
"vegetables": [
{"type": "vegetables", "quantity": 5 }
],
"fruit": [
{ "type": "fruit", "quantity": 1 },
{ "type": "fruit", "quantity": 5 }
],
"meat": [
{ "type": "meat", "quantity": 23 },
{ "type": "meat", "quantity": 22 }
]
}
```

<!-- tabs:end -->



## <%...%> :id=standard-syntax
Expand Down
12 changes: 8 additions & 4 deletions src/extensions/customized_eta.ts
Expand Up @@ -73,6 +73,7 @@ const eta = new CustomizedEta({
'function out(x){__eta.res+=__eta.f(x)}',
'function outn(x){__eta.res+=__eta.f(x)+"\\n"}',
].join('\n') + '\n',
bodyHeader: '_.init()',

autoEscape: false, /** Automatically XML-escape interpolations */
// escapeFunction: eta.XMLEscape,
Expand Down Expand Up @@ -243,12 +244,14 @@ function compile(this: Eta, str: string, options?: Partial<Options>): TemplateFu
}
}
function compileToString(this: Eta, str: string, options?: Partial<Options>): string {
const config = this.config;
const isAsync = options && options.async;
const config = this.config
// @ts-expect-error
const bodyHeader = config.bodyHeader
const isAsync = options && options.async

const compileBody = this.compileBody;
const compileBody = this.compileBody

const buffer: Array<AstObject> = this.parse.call(this, str);
const buffer: Array<AstObject> = this.parse.call(this, str)

let res = `${config.functionHeader}
let __eta = {res: "", e: this.config.escapeFunction, f: this.config.filterFunction${
Expand All @@ -259,6 +262,7 @@ let __eta = {res: "", e: this.config.escapeFunction, f: this.config.filterFuncti
: ""
}}
${config.debug ? "try {" : ""}${config.useWith ? "with(" + config.varName + "||{}){" : ""}
${bodyHeader}
${compileBody.call(this, buffer)}
${config.useWith ? "}" : ""}${
config.debug
Expand Down
52 changes: 52 additions & 0 deletions src/tags.ts
Expand Up @@ -526,12 +526,59 @@ async function links(
return linksInBlock
}


/* internal */
function array_zip(...arr: any[]) {
return Array(
Math.min(...arr.map(a => a.length))
)
.fill(undefined)
.map((_, i) => arr.map(a => a[i]))
}
function array_unique() {
// @ts-expect-error
return [...new Set(this)]
}
function array_groupby(key: Function) {
// @ts-expect-error
return Object.groupBy(this, key)
}
function array_sorted(key: Function) {
// @ts-expect-error
return this
.map((x) => [(key ? key(x) : x), x])
.sort((a, b) => {
a = a[0]; b = b[0];
if (!Array.isArray(a)) a = [a];
if (!Array.isArray(b)) b = [b];
for (let i = 0; i < a.length; i++) {
const xa = a[i].toString()
const xb = b[i].toString()
const d = xa.localeCompare(xb, 'en', {numeric: true})
if (d !== 0) return d;
}
return 0
})
.map((p) => p[1])
}


function bindContext(f, context) {
const func = f.bind(null, context)
const signature = f.toString().replace('context, ', '')
func.toString = () => signature
return func
}
function _initContext() {
// @ts-expect-error
Array.zip = array_zip
// @ts-expect-error
Array.prototype.unique = array_unique
// @ts-expect-error
Array.prototype.groupby = array_groupby
// @ts-expect-error
Array.prototype.sorted = array_sorted
}

export function getTemplateTagsDatesContext() {
const todayObj = dayjs().startOf('second')
Expand Down Expand Up @@ -560,6 +607,11 @@ export function getTemplateTagsContext(context: ILogseqContext) {
const datesContext = getTemplateTagsDatesContext()

return new Context({
_: {
init: _initContext,
array_zip,
},

ref, bref, tag, embed,
empty, bool, when, fill, zeros, spaces,

Expand Down

0 comments on commit e7b24ec

Please sign in to comment.