{"id":20516630,"url":"https://github.com/block/shnip","last_synced_at":"2025-09-25T11:30:37.635Z","repository":{"id":261862304,"uuid":"867892047","full_name":"block/shnip","owner":"block","description":null,"archived":false,"fork":false,"pushed_at":"2024-11-13T23:01:18.000Z","size":17236,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-07T14:03:40.089Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/block.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-10-05T00:06:09.000Z","updated_at":"2024-11-13T23:00:57.000Z","dependencies_parsed_at":"2024-11-08T21:34:20.396Z","dependency_job_id":"8d65ca2f-2fc6-4d5b-aac6-4399660ac012","html_url":"https://github.com/block/shnip","commit_stats":null,"previous_names":["block/shnip"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/block%2Fshnip","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/block%2Fshnip/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/block%2Fshnip/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/block%2Fshnip/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/block","download_url":"https://codeload.github.com/block/shnip/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234178395,"owners_count":18791724,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-11-15T21:29:52.177Z","updated_at":"2025-09-25T11:30:32.268Z","avatar_url":"https://github.com/block.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Shnip\n\nShnip is a versatile code snippet extraction tool designed to help you manage and organize code snippets from your source files, particularly your test suites. It allows you to use your written tests as source code for content that gets surfaced in documentation.\n\n## Features\n\n- **Leverage Test Suites**: Use your existing tests as the source for documentation snippets.\n- **Customizable Snippet Extraction**: Define custom tags to mark the start and end of code snippets.\n- **Multi-Language Support**: Works with various programming languages by specifying file extensions.\n- **Flexible Output Structure**: Choose how your snippets are organized in the output directory.\n- **Prepend Blocks**: Include import statements or other code that should precede your snippets.\n- **CLI Integration**: Use the command-line interface for easy integration into your build process.\n\n## Installation\n\nInstall Shnip using npm:\n\n```\nnpm install shnip\n```\n\nOr with pnpm:\n\n```\npnpm install shnip\n```\n\n## Getting Started\n\n### Configuration\n\nCreate a `shnip.config.ts` file in the root directory of your project:\n\n```typescript\nexport const config = {\n  rootDirectory: \"./src\", // Directory containing source files\n  snippetOutputDirectory: \"./snippets\", // Directory to store extracted snippets\n  fileExtensions: [\".js\", \".ts\", \".kt\", \".gradle\", \".xml\", \".bash\", \".swift\"], // Supported file types\n  exclude: [\"excludeThisSnippet\"], // Snippets to exclude\n  snippetTags: {\n    start: \":snippet-start:\",\n    end: \":snippet-end:\",\n    prependStart: \":prepend-start:\",\n    prependEnd: \":prepend-end:\",\n  },\n  outputDirectoryStructure: \"byLanguage\", // How snippets are organized\n  version: \"1.0.0\", // Versioning for output directories\n};\n```\n\n## Adding Snippets to Your Test Files\n\nMark the code you want to extract using the custom snippet tags defined in your configuration. By placing these tags in your test suites, you can directly extract code examples from your tests.\n\n### Example in a TypeScript test file:\n\n```typescript\n// :snippet-start: exampleTestSnippet\ntest(\"should greet the user\", () =\u003e {\n  const name = \"Alice\";\n  const greeting = greet(name);\n  expect(greeting).toBe(\"Hello, Alice!\");\n});\n// :snippet-end:\n```\n\n### Using Prepend Blocks\n\nInclude code that should be prepended to your snippets, such as import statements.\n\n```typescript\n// :prepend-start: exampleTestSnippet\nimport { greet } from \"../src/greet\";\n// :prepend-end:\n```\n\n## Extracting Snippets\n\nUse the Shnip CLI to extract snippets based on your configuration.\n\n### Running the Extractor\n\n```\nnpx shnip\n```\n\nOr add a script to your `package.json`:\n\n```json\n\"scripts\": {\n  \"extract-snippets\": \"shnip\"\n}\n```\n\nThen run:\n\n```\nnpm run extract-snippets\n```\n\n## Using Extracted Snippets in Documentation\n\nImport the extracted snippets into your documentation or application.\n\n### Example in a React Component for Documentation:\n\n```jsx\nimport exampleTestSnippet from \"./snippets/1.0.0/typescript/exampleTestSnippet.snippet.js\";\n\nfunction Documentation() {\n  return \u003cCodeBlock language=\"typescript\"\u003e{exampleTestSnippet}\u003c/CodeBlock\u003e;\n}\n```\n\n## CLI Options\n\nShnip provides several command-line options for additional control.\n\n### Clear Output Directory\n\nRemove all extracted snippets.\n\n```\nnpx shnip clear\n```\n\n### Specify Output Structure\n\nChoose how snippets are organized (`flat`, `match`, `organized`, `byLanguage`).\n\n```\nnpx shnip --structure byLanguage\n```\n\n## API Reference\n\n### `SnippetExtractor` Class\n\nMain class responsible for extracting snippets.\n\n**Importing:**\n\n```typescript\nimport { SnippetExtractor } from \"shnip\";\n```\n\n**Usage:**\n\n```typescript\nconst extractor = new SnippetExtractor(config);\nextractor.extractSnippets();\n```\n\n### `getSnippet` Function\n\nAsynchronously retrieves a snippet's content.\n\n**Importing:**\n\n```typescript\nimport { getSnippet } from \"shnip\";\n```\n\n**Usage:**\n\n```typescript\nconst snippetContent = await getSnippet(\"exampleTestSnippet\", \"typescript\");\n```\n\n**Parameters:**\n\n- `snippetName` (string): The name of the snippet to retrieve.\n- `language` (string): The programming language of the snippet (default is `'javascript'`).\n\n## Configuration Options\n\n- **`rootDirectory`**: Root directory containing the source files (e.g., your test suites).\n- **`snippetOutputDirectory`**: Directory where snippets will be saved.\n- **`fileExtensions`**: Array of file extensions to process.\n- **`exclude`**: Array of snippet names to exclude from extraction.\n- **`snippetTags`**: Custom tags to identify snippet boundaries.\n  - `start`: Tag indicating the start of a snippet.\n  - `end`: Tag indicating the end of a snippet.\n  - `prependStart`: Tag indicating the start of a prepend block.\n  - `prependEnd`: Tag indicating the end of a prepend block.\n- **`outputDirectoryStructure`**: Determines how snippets are organized in the output directory.\n- **`version`**: Version identifier used in the output directory path.\n\n## Output Directory Structures\n\n- **`flat`**: All snippets are placed in a single directory.\n- **`match`**: Snippets mirror the directory structure of the source files.\n- **`organized`**: Snippets are organized based on custom logic.\n- **`byLanguage`**: Snippets are grouped by programming language (default).\n\n## Examples\n\n### Extracting and Using a Test Snippet\n\n**Test File (`tests/greet.test.ts`):**\n\n```typescript\n// :prepend-start: greetTest\nimport { greet } from \"../src/greet\";\n// :prepend-end:\n\n// :snippet-start: greetTest\ntest(\"should greet the user\", () =\u003e {\n  const name = \"Bob\";\n  const greeting = greet(name);\n  expect(greeting).toBe(\"Hello, Bob!\");\n});\n// :snippet-end:\n```\n\n**Extract Snippets:**\n\n```\nnpx shnip\n```\n\n**Use Extracted Snippet in Documentation:**\n\n```jsx\nimport greetTest from \"./snippets/1.0.0/typescript/greetTest.snippet.js\";\n\nfunction GreetTestDocs() {\n  return \u003cCodeBlock language=\"typescript\"\u003e{greetTest}\u003c/CodeBlock\u003e;\n}\n```\n\n## Troubleshooting\n\n### Unexpected Virtual Store Location Error\n\nIf you encounter an error regarding the virtual store location, reinstall your dependencies:\n\n```\npnpm install\n```\n\nAlternatively, specify the virtual store directory in your `.npmrc` file:\n\n```\nvirtual-store-dir = \"node_modules/.pnpm\"\n```\n\n### Linking Issues\n\nTo link `shnip` as a local package:\n\n```\npnpm link --dir ./example\n```\n\nOr add it as a dependency in your `package.json` using a relative path:\n\n```json\n\"dependencies\": {\n  \"shnip\": \"file:../shnip\"\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblock%2Fshnip","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblock%2Fshnip","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblock%2Fshnip/lists"}