{"id":43122863,"url":"https://github.com/iwe7/iwe7-underscore","last_synced_at":"2026-01-31T20:03:44.478Z","repository":{"id":57278857,"uuid":"127956874","full_name":"iwe7/iwe7-underscore","owner":"iwe7","description":"iwe7-underscore","archived":false,"fork":false,"pushed_at":"2018-04-03T19:16:10.000Z","size":4,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-30T19:29:56.067Z","etag":null,"topics":["angular","pipe","underscore"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/iwe7.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-04-03T19:14:28.000Z","updated_at":"2018-04-03T19:20:04.000Z","dependencies_parsed_at":"2022-09-18T08:41:59.072Z","dependency_job_id":null,"html_url":"https://github.com/iwe7/iwe7-underscore","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/iwe7/iwe7-underscore","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iwe7%2Fiwe7-underscore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iwe7%2Fiwe7-underscore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iwe7%2Fiwe7-underscore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iwe7%2Fiwe7-underscore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iwe7","download_url":"https://codeload.github.com/iwe7/iwe7-underscore/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iwe7%2Fiwe7-underscore/sbom","scorecard":{"id":498840,"data":{"date":"2025-08-11","repo":{"name":"github.com/iwe7/iwe7-underscore","commit":"e9ffe8b6c73fa51165bc8cb91cd5968b4483ddc1"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.6,"checks":[{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Code-Review","score":0,"reason":"Found 0/2 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-19T21:16:52.622Z","repository_id":57278857,"created_at":"2025-08-19T21:16:52.622Z","updated_at":"2025-08-19T21:16:52.622Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28952582,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-31T18:30:42.805Z","status":"ssl_error","status_checked_at":"2026-01-31T18:30:19.593Z","response_time":128,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","pipe","underscore"],"created_at":"2026-01-31T20:03:27.237Z","updated_at":"2026-01-31T20:03:44.462Z","avatar_url":"https://github.com/iwe7.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 项目背景\n\u003e 今天心血来潮，以前不常写东西，接触angular以来，觉得有必要分享一些新的体会了，于是来到了这里。\n\n- 管道Pipe可以将数据作为输入，然后按照规则将其转换并输出。\n\n## 创建项目\n```sh\nng new meepo-underscore\ncd meepo-underscore\n```\n\n## 创建module和初始化pipe\n```sh\nng g m meepo-underscore\nng g pipe map\nng g pipe flatten\nng g pipe invert\nng g pipe range\nng g pipe sample\nng g pipe shuffle\nng g pipe values\n```\n\n## 分析需求及实现\n\n- map 结构转数组\n\u003e meepo-underscore/map.pipe.ts\n```ts\nimport { Pipe, PipeTransform } from \"@angular/core\";\nimport * as _ from \"underscore\";\n@Pipe({\n  name: \"map\"\n})\nexport class MapPipe implements PipeTransform {\n  transform(value: any, args?: any): any {\n    let re = _.map(value, (item, key) =\u003e {\n      return { item: item, key: key };\n    });\n    return re;\n  }\n}\n```\n- 使用\n```ts\nlet obj = {\n    name: \"bob\",\n    school: \"school\",\n    address: \"xueyuan\"\n}\n```\n```html\n\u003cdiv *ngFor=\"let item of obj | map\"\u003e\n    {{item.key}}:{{item.item}}\n\u003c/div\u003e\n```\n- flatten 接收一个Array，无论这个Array里面嵌套了多少个Array，flatten()最后都把它们变成一个一维数组\n\u003e meepo-underscore/flatten.pipe.ts\n```ts\nimport { Pipe, PipeTransform } from \"@angular/core\";\nimport * as _ from \"underscore\";\n\n@Pipe({\n  name: \"flatten\"\n})\nexport class FlattenPipe implements PipeTransform {\n  transform(value: any, args?: any): any {\n    return _.flatten(value);\n  }\n}\n```\n- 使用\n```html\n\u003cdiv *ngFor=\"let item of [[1],[2],[3,4,5]] | flatten\"\u003e\n    {{item.key}}:{{item.item}}\n\u003c/div\u003e\n```\n- invert 把object的每个key-value来个交换，key变成value，value变成key\n```ts\nimport { Pipe, PipeTransform } from '@angular/core';\nimport * as _ from \"underscore\";\n\n@Pipe({\n  name: 'invert'\n})\nexport class InvertPipe implements PipeTransform {\n  transform(value: any, args?: any): any {\n    return _.invert(value);\n  }\n}\n```\n- 使用\n```html\n\u003cdiv *ngFor=\"let item of [{key1:'item1'},{key2:'item2'}] | invert | map\"\u003e\n    {{item.key}}:{{item.item}}\n\u003c/div\u003e\n```\n- range 区间数组\n```ts\nimport { Pipe, PipeTransform } from \"@angular/core\";\nimport * as _ from \"underscore\";\n\n@Pipe({\n  name: \"range\"\n})\nexport class RangePipe implements PipeTransform {\n  transform(value: any, args?: any): any {\n    return _.range(value, args);\n  }\n}\n```\n- 使用\n```html\n\u003cdiv *ngFor=\"let item of 0 | range:10\"\u003e\n    {{item}}\n\u003c/div\u003e\n```\n- sample 随机选择一个或多个元素：\n```ts\nimport { Pipe, PipeTransform } from \"@angular/core\";\nimport * as _ from \"underscore\";\n\n@Pipe({\n  name: \"sample\"\n})\nexport class SamplePipe implements PipeTransform {\n  transform(value: any, args?: any): any {\n    let item = _.sample(value, args);\n    return item;\n  }\n}\n\n```\n- 使用\n```html\n\u003ch2 class=\"title\"\u003e_.sample\u003c/h2\u003e\n\u003cdiv *ngFor=\"let item of obj | map | sample:4\"\u003e\n  {{item.item}}\n\u003c/div\u003e\n```\n- shuffle 用洗牌算法随机打乱一个集合\n```ts\nimport { Pipe, PipeTransform } from '@angular/core';\nimport * as _ from \"underscore\";\n\n@Pipe({\n  name: 'shuffle'\n})\nexport class ShufflePipe implements PipeTransform {\n\n  transform(value: any, args?: any): any {\n    return _.shuffle(value)\n  }\n\n}\n\n```\n\n```html\n\u003ch2 class=\"title\"\u003e_.shuffle\u003c/h2\u003e\n\u003cdiv *ngFor=\"let item of obj | map | shuffle\"\u003e\n  {{item.key}}-{{item.item}}\n\u003c/div\u003e\n```\n- values 对象值遍历\n\n```ts\nimport { Pipe, PipeTransform } from '@angular/core';\nimport * as _ from \"underscore\";\n\n@Pipe({\n  name: 'values'\n})\nexport class ValuesPipe implements PipeTransform {\n\n  transform(value: any, args?: any): any {\n    return _.values(value);\n  }\n\n}\n\n```\n\n\n### 发布准备\n新建package.json\n```json\n{\n    \"name\": \"meepo-underscore\",\n    \"version\": \"2.0.2\",\n    \"repository\": \"https://github.com/meepobrother/meepo-underscore.git\",\n    \"author\": \"imeepos \u003c1037483576@qq.com\u003e\",\n    \"license\": \"MIT\",\n    \"private\": false,\n    \"scripts\": {\n        \"git\": \"git add . \u0026\u0026 git commit -m 'push to save' \u0026\u0026 git push origin master\"\n    },\n    \"peerDependencies\": {\n        \"@angular/core\": \"*\",\n        \"@angular/common\": \"*\",\n        \"rxjs\": \"*\",\n        \"underscore\": \"*\"\n    },\n    \"ngPackage\": {\n        \"$schema\": \"./node_modules/ng-packagr/ng-package.schema.json\",\n        \"dest\": \"../../../meepo/underscore\",\n        \"workingDirectory\": \"./.ng_build\",\n        \"lib\": {\n            \"entryFile\": \"./public_api.ts\"\n        }\n    }\n}\n```\n导出模块\n```ts\nimport { NgModule } from \"@angular/core\";\nimport { CommonModule } from \"@angular/common\";\nimport { MapPipe } from \"./map.pipe\";\nimport { ShufflePipe } from \"./shuffle.pipe\";\nimport { SamplePipe } from \"./sample.pipe\";\nimport { RangePipe } from \"./range.pipe\";\nimport { FlattenPipe } from \"./flatten.pipe\";\nimport { ValuesPipe } from \"./values.pipe\";\nimport { InvertPipe } from \"./invert.pipe\";\n\nexport const PIPES = [\n  MapPipe,\n  ShufflePipe,\n  SamplePipe,\n  RangePipe,\n  FlattenPipe,\n  ValuesPipe,\n  InvertPipe\n];\n\n@NgModule({\n  imports: [CommonModule],\n  declarations: [...PIPES],\n  exports: [...PIPES]\n})\nexport class UnderscoreModule {}\n\n```\n\n## 发布到npm\n\n```sh\nng-packagr -p ./src/app/shared/underscore/package.json\n```\n\n## 使用安装\n\n```sh\nyarn add meepo-underscore\n```\n\n```ts\nimport { BrowserModule } from '@angular/platform-browser';\nimport { NgModule } from '@angular/core';\n\n\nimport { AppComponent } from './app.component';\nimport { RouterModule } from '@angular/router';\nimport { UnderscoreModule } from 'meepo-underscore';\n\n@NgModule({\n  declarations: [\n    AppComponent\n  ],\n  imports: [\n    BrowserModule,\n    RouterModule.forRoot([]),\n    UnderscoreModule\n  ],\n  providers: [],\n  bootstrap: [AppComponent]\n})\nexport class AppModule { }\n\n```\n\n### 总结\n本文介绍了 Angular 自定义管道pipe的方法，并发布到npm, 方便使用及管理。\n\n[项目地址](https://github.com/iwe7/iwe7-underscore.git)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiwe7%2Fiwe7-underscore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fiwe7%2Fiwe7-underscore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiwe7%2Fiwe7-underscore/lists"}