{"id":36754705,"url":"https://github.com/gofunct/stencil","last_synced_at":"2026-01-12T12:48:28.555Z","repository":{"id":57571221,"uuid":"164124613","full_name":"gofunct/stencil","owner":"gofunct","description":null,"archived":false,"fork":false,"pushed_at":"2019-02-01T04:47:13.000Z","size":17365,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2023-08-20T22:11:48.986Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","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/gofunct.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}},"created_at":"2019-01-04T15:36:51.000Z","updated_at":"2019-02-01T04:47:15.000Z","dependencies_parsed_at":"2022-09-14T23:35:18.709Z","dependency_job_id":null,"html_url":"https://github.com/gofunct/stencil","commit_stats":null,"previous_names":[],"tags_count":0,"template":null,"template_full_name":null,"purl":"pkg:github/gofunct/stencil","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gofunct%2Fstencil","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gofunct%2Fstencil/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gofunct%2Fstencil/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gofunct%2Fstencil/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gofunct","download_url":"https://codeload.github.com/gofunct/stencil/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gofunct%2Fstencil/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28338983,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T12:22:26.515Z","status":"ssl_error","status_checked_at":"2026-01-12T12:22:10.856Z","response_time":98,"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":[],"created_at":"2026-01-12T12:48:28.491Z","updated_at":"2026-01-12T12:48:28.545Z","avatar_url":"https://github.com/gofunct.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# stencil\n--\n    import \"github.com/gofunct/stencil\"\n\n\n## Usage\n\n```go\nconst (\n\t// CaptureStdout is a bitmask to capture STDOUT\n\tCaptureStdout = 1\n\t// CaptureStderr is a bitmask to capture STDERR\n\tCaptureStderr = 2\n\t// CaptureBoth captures STDOUT and STDERR\n\tCaptureBoth = CaptureStdout + CaptureStderr\n)\n```\n\n```go\nvar Env string\n```\nEnv is the default environment to use for all commands. That is, the effective\nenvironment for all commands is the merged set of (parent environment, Env, func\nspecified environment). Whitespace or newline separate key value pairs. $VAR\ninterpolation is allowed.\n\nEnv = \"GOOS=linux GOARCH=amd64\" Env = `\n\n    GOOS=linux\n    GOPATH=./vendor:$GOPATH\n\n`\n\n```go\nvar InheritParentEnv bool\n```\nInheritParentEnv whether to inherit parent's environment\n\n```go\nvar PathListSeparator = \"::\"\n```\nPathListSeparator is a cross-platform path list separator. On Windows,\nPathListSeparator is replacd by \";\". On others, PathListSeparator is replaced by\n\":\"\n\n```go\nvar Processes = make(map[string]*os.Process)\n```\nProcesses are the processes spawned by Start()\n\n```go\nvar Verbose = false\n```\nVerbose indicates whether to log verbosely\n\n```go\nvar Version = \"v0.0.1\"\n```\nVersion is the current version\n\n```go\nvar (\n\n\t// WaitMs is the default time (1500 ms) to debounce task events in watch mode.\n\tWait time.Duration\n)\n```\n\n#### func  Bash\n\n```go\nfunc Bash(script string, options ...map[string]interface{}) (string, error)\n```\nBash executes a bash script (string).\n\n#### func  BashOutput\n\n```go\nfunc BashOutput(script string, options ...map[string]interface{}) (string, error)\n```\nBashOutput executes a bash script and returns the output\n\n#### func  EffectiveEnv\n\n```go\nfunc EffectiveEnv(funcEnv []string) []string\n```\nEffectiveEnv is the effective environment for an exec function.\n\n#### func  GetWatchDelay\n\n```go\nfunc GetWatchDelay() time.Duration\n```\nGetWatchDelay gets the watch delay\n\n#### func  Getenv\n\n```go\nfunc Getenv(key string) string\n```\nGetenv environment variable from a string array.\n\n#### func  GoThrottle\n\n```go\nfunc GoThrottle(throttle int, fns ...func() error) error\n```\nGoThrottle starts to run the given list of fns concurrently, at most n fns at a\ntime.\n\n#### func  Halt\n\n```go\nfunc Halt(v interface{})\n```\nHalt is a soft panic and stops a task.\n\n#### func  Inside\n\n```go\nfunc Inside(dir string, lambda func()) error\n```\nInside temporarily changes the working directory and restores it when lambda\nfinishes.\n\n#### func  ParseStringEnv\n\n```go\nfunc ParseStringEnv(s string) []string\n```\nParseStringEnv parse the package Env string and converts it into an environment\nslice.\n\n#### func  Prompt\n\n```go\nfunc Prompt(prompt string) string\n```\nPrompt prompts user for input with default value.\n\n#### func  PromptPassword\n\n```go\nfunc PromptPassword(prompt string) string\n```\nPromptPassword prompts user for password input.\n\n#### func  Run\n\n```go\nfunc Run(commandstr string, options ...map[string]interface{}) (string, error)\n```\nRun runs a command.\n\n#### func  RunOutput\n\n```go\nfunc RunOutput(commandstr string, options ...map[string]interface{}) (string, error)\n```\nRunOutput runs a command and returns output.\n\n#### func  SetEnviron\n\n```go\nfunc SetEnviron(envstr string, inheritParent bool)\n```\nSetEnviron sets the environment for child processes. Note that SetEnviron(Env,\nInheritParentEnv) is called once automatically.\n\n#### func  SetWatchDelay\n\n```go\nfunc SetWatchDelay(delay time.Duration)\n```\nSetWatchDelay sets the time duration between watches.\n\n#### func  Start\n\n```go\nfunc Start(commandstr string, options ...map[string]interface{}) error\n```\nStart starts an async command. If executable has suffix \".go\" then it will be\n\"go install\"ed then executed. Use this for watching a server task.\n\nIf Start is called with the same command it kills the previous process.\n\nThe working directory is optional.\n\n#### func  Stencil\n\n```go\nfunc Stencil(tasksFunc func(*Project))\n```\nStencil runs a project of tasks.\n\n#### func  Usage\n\n```go\nfunc Usage(tasks string)\n```\nUsage prints a usage screen with task descriptions.\n\n#### type Asset\n\n```go\ntype Asset struct {\n\tbytes.Buffer\n\tInfo *glob.FileAsset\n\t// WritePath is the write destination of the asset.\n\tWritePath string\n\tPipeline  *Pipeline\n}\n```\n\nAsset is any file which can be loaded and processed by a filter.\n\n#### func (*Asset) ChangeExt\n\n```go\nfunc (asset *Asset) ChangeExt(newExt string)\n```\nChangeExt changes the extension of asset.WritePath. ChangExt is used by filters\nwhich transpile source. For example, a filter for Markdown would use\nChangeExt(\".html\") to write the asset as an HTML file.\n\n#### func (*Asset) Dump\n\n```go\nfunc (asset *Asset) Dump() string\n```\nDump returns a console friendly representation of asset. Note, String() returns\nthe string value of Buffer.\n\n#### func (*Asset) Ext\n\n```go\nfunc (asset *Asset) Ext() string\n```\nExt returns the extension of asset.WritePath.\n\n#### func (*Asset) IsText\n\n```go\nfunc (asset *Asset) IsText() bool\n```\nIsText return true if it thinks this asset is text based, meaning it can be\nmanipulated with string functions.\n\n#### func (*Asset) MimeType\n\n```go\nfunc (asset *Asset) MimeType() string\n```\nMimeType returns an educated guess of the content type of asset.\n\n#### func (*Asset) Rewrite\n\n```go\nfunc (asset *Asset) Rewrite(bytes []byte)\n```\nRewrite sets the buffer to bytes.\n\n#### func (*Asset) RewriteString\n\n```go\nfunc (asset *Asset) RewriteString(s string)\n```\nRewriteString sets the buffer to a string value.\n\n#### type Context\n\n```go\ntype Context struct {\n\t// Task is the currently running task.\n\tJob *Job\n\n\tPipeline *Pipeline\n\n\t// FileEvent is an event from the watcher with change details.\n\tFileEvent *watcher.FileEvent\n\n\t// Task command line arguments\n\tArgs minimist.ArgMap\n\n\tError error\n}\n```\n\nContext is the data passed to a task.\n\n#### func (*Context) AnyFile\n\n```go\nfunc (context *Context) AnyFile() []string\n```\nAnyFile returns either a non-DELETe FileEvent file or the WatchGlob patterns\nwhich can be used by goa.Load()\n\n#### func (*Context) Bash\n\n```go\nfunc (context *Context) Bash(cmd string, options ...map[string]interface{})\n```\nBash runs a bash shell.\n\n#### func (*Context) BashOutput\n\n```go\nfunc (context *Context) BashOutput(script string, options ...map[string]interface{}) string\n```\nBashOutput executes a bash script and returns the output\n\n#### func (*Context) Check\n\n```go\nfunc (context *Context) Check(err error, msg string)\n```\nCheck halts the task if err is not nil.\n\nDo this\n\n    Check(err, \"Some error occured\")\n\nInstead of\n\n    if err != nil {\n    \tHalt(err)\n    }\n\n#### func (*Context) Pipe\n\n```go\nfunc (context *Context) Pipe(filters ...interface{})\n```\nBash runs a bash shell.\n\n#### func (*Context) Run\n\n```go\nfunc (context *Context) Run(cmd string, options ...map[string]interface{})\n```\nRun runs a command\n\n#### func (*Context) RunOutput\n\n```go\nfunc (context *Context) RunOutput(commandstr string, options ...map[string]interface{}) string\n```\nRunOutput runs a command and returns output.\n\n#### func (*Context) Start\n\n```go\nfunc (context *Context) Start(cmd string, options ...map[string]interface{})\n```\nStart run aysnchronously.\n\n#### type Dependency\n\n```go\ntype Dependency interface {\n\t// contains filtered or unexported methods\n}\n```\n\nDependency marks an interface as a dependency.\n\n#### type Handler\n\n```go\ntype Handler interface {\n\tHandle(*Context)\n}\n```\n\nHandler is the interface which all task handlers eventually implement.\n\n#### type HandlerFunc\n\n```go\ntype HandlerFunc func(*Context)\n```\n\nHandlerFunc is a Handler adapter.\n\n#### func (HandlerFunc) Handle\n\n```go\nfunc (f HandlerFunc) Handle(ctx *Context)\n```\nHandle implements Handler.\n\n#### type Job\n\n```go\ntype Job struct {\n\tName string\n\n\tHandler Handler\n\n\t// computed based on dependencies\n\tEffectiveWatchRegexps []*glob.RegexpInfo\n\tEffectiveWatchGlobs   []string\n\n\t// Complete indicates whether this task has already ran. This flag is\n\t// ignored in watch mode.\n\tComplete bool\n\n\tRunOnce bool\n\n\tSrcFiles   []*glob.FileAsset\n\tSrcGlobs   []string\n\tSrcRegexps []*glob.RegexpInfo\n\n\tDestFiles   []*glob.FileAsset\n\tDestGlobs   []string\n\tDestRegexps []*glob.RegexpInfo\n\n\t// used when a file event is received between debounce intervals, the file event\n\t// will queue itself and set this flag and force debounce to run it\n\t// when time has elapsed\n\tsync.Mutex\n}\n```\n\nA Task is an operation performed on a user's project directory.\n\n#### func  NewJob\n\n```go\nfunc NewJob(name string, argm minimist.ArgMap) *Job\n```\nNewTask creates a new Task.\n\n#### func (*Job) DependencyNames\n\n```go\nfunc (j *Job) DependencyNames() []string\n```\nDependencyNames gets the flattened dependency names.\n\n#### func (*Job) Deps\n\n```go\nfunc (j *Job) Deps(names ...interface{})\n```\nDeps are task dependencies and must specify how to run jobs in series or in\nparallel.\n\n#### func (*Job) Desc\n\n```go\nfunc (j *Job) Desc(desc string) *Job\n```\nDesc is alias for Description.\n\n#### func (*Job) Description\n\n```go\nfunc (j *Job) Description(desc string) *Job\n```\nDescription sets the description for the task.\n\n#### func (*Job) Dest\n\n```go\nfunc (j *Job) Dest(globs ...string) *Job\n```\nDest adds target globs which are used to calculated outdated files. The jobs is\nnot run unless ANY file Src are newer than ANY in DestN.\n\n#### func (*Job) Run\n\n```go\nfunc (j *Job) Run() error\n```\nRun runs all the dependencies of this job and when they have completed, runs\nthis job.\n\n#### func (*Job) RunWithEvent\n\n```go\nfunc (j *Job) RunWithEvent(logName string, e *watcher.FileEvent) (err error)\n```\nRunWithEvent runs this task when triggered from a watch. *e* FileEvent contains\ninformation about the file/directory which changed in watch mode.\n\n#### func (*Job) Src\n\n```go\nfunc (j *Job) Src(globs ...string) *Job\n```\nSrc adds a source globs to this task. The task is not run unless files are\noutdated between Src and Dest globs.\n\n#### func (*Job) Wait\n\n```go\nfunc (j *Job) Wait(duration time.Duration) *Job\n```\nWait is minimum milliseconds before task can run again\n\n#### type M\n\n```go\ntype M map[string]interface{}\n```\n\nM is generic string to interface alias\n\n#### type Message\n\n```go\ntype Message struct {\n\tEvent string\n\tData  string\n}\n```\n\nMessage are sent on the Events channel\n\n#### type P\n\n```go\ntype P []interface{}\n```\n\nP is alias for Parallel\n\n#### type Parallel\n\n```go\ntype Parallel []interface{}\n```\n\nParallel runs jobs in parallel\n\n#### type Pipeline\n\n```go\ntype Pipeline struct {\n\tAssets  []*Asset\n\tFilters []interface{}\n}\n```\n\nPipeline is a asset flow through which each asset is processed by one or more\nfilters. For text files this could be something as simple as adding a header or\nminification. Some filters process assets in batches combining them, for example\nconcatenating JavaScript or CSS.\n\n#### func  NewPipeline\n\n```go\nfunc NewPipeline() *Pipeline\n```\n\n#### func  Pipe\n\n```go\nfunc Pipe(filters ...interface{}) (*Pipeline, error)\n```\nPipe creates a pipeline with filters and runs it.\n\n#### func (*Pipeline) AddAsset\n\n```go\nfunc (pipeline *Pipeline) AddAsset(asset *Asset)\n```\nAddAsset adds an asset\n\n#### func (*Pipeline) Pipe\n\n```go\nfunc (pipeline *Pipeline) Pipe(filters ...interface{}) *Pipeline\n```\nPipe adds one or more filters to the pipeline. Pipe may be called more than\nonce.\n\nFilters are simple function. Options are handle through closures. The supported\nhandlers are\n\n1. Single asset handler. Use this to transorm each asset individually.\n\n    AddHeader filter is an example.\n\n      // signature\n      func(*pipeline.Asset) error\n\n2. Multi asset handler. Does not modify the number of elements. See\n\n    Write filter is an example.\n\n      //  signature\n      func(assets []*pipeline.Asset) error\n\n3. Pipeline handler. Use this to have unbridled control. Load filter\n\n    is an example.\n\n      // signature\n      func(*Pipeline) error\n\n#### func (*Pipeline) Run\n\n```go\nfunc (pipeline *Pipeline) Run()\n```\nRun runs assets through the pipeline.\n\n#### func (*Pipeline) Truncate\n\n```go\nfunc (pipeline *Pipeline) Truncate()\n```\nTruncate removes all assets, resetting Assets to empty slice.\n\n#### type Project\n\n```go\ntype Project struct {\n\tsync.Mutex\n\tJobs      map[string]*Job\n\tNamespace map[string]*Project\n}\n```\n\nProject is a container for tasks.\n\n#### func  NewProject\n\n```go\nfunc NewProject(tasksFunc func(*Project), exitFn func(code int), argm minimist.ArgMap) *Project\n```\nNewProject creates am empty project ready for tasks.\n\n#### func (*Project) Define\n\n```go\nfunc (project *Project) Define(fn func(*Project))\n```\nDefine defines tasks\n\n#### func (*Project) Exit\n\n```go\nfunc (project *Project) Exit(code int)\n```\nExit quits the project.\n\n#### func (*Project) Func\n\n```go\nfunc (project *Project) Func(name string, dependencies Dependency, handler func(*Context)) *Job\n```\nTask adds a task to the project with dependencies and handler.\n\n#### func (*Project) Func1\n\n```go\nfunc (project *Project) Func1(name string, handler func(*Context)) *Job\n```\nDo1 adds a simple task to the project.\n\n#### func (*Project) FuncD\n\n```go\nfunc (project *Project) FuncD(name string, dependencies Dependency) *Job\n```\nTaskD adds a task which runs other dependencies with no handler.\n\n#### func (*Project) Run\n\n```go\nfunc (project *Project) Run(name string) error\n```\nRun runs a task by name.\n\n#### func (*Project) Use\n\n```go\nfunc (project *Project) Use(namespace string, tasksFunc func(*Project))\n```\nUse uses another project's task within a namespace.\n\n#### func (*Project) Watch\n\n```go\nfunc (project *Project) Watch(names []string, isParent bool) bool\n```\nWatch watches the Files of a task and reruns the task on a watch event. Any\ndirect dependency is also watched. Returns true if watching.\n\nTODO: 1. Only the parent task watches, but it gathers wath info from all\ndependencies.\n\n2. Anything without src files always run when a dependency is triggered by a\nglob match.\n\n    build [generate{*.go} compile] =\u003e go file changes =\u003e  build, generate and compile\n\n3. Tasks with src only run if it matches a src\n\n    build [generate{*.go} css{*.scss} compile] =\u003e go file changes =\u003e build, generate and compile\n    css does not need to run since no SCSS files ran\n\nX depends on [A:txt, B] =\u003e txt changes A runs, X runs without deps X:txt on [A,\nB] =\u003e txt changes A, B, X runs\n\n#### type S\n\n```go\ntype S []interface{}\n```\n\nS is alias for Series\n\n#### type Series\n\n```go\ntype Series []interface{}\n```\n\nSeries are dependent jobs which must run in series.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgofunct%2Fstencil","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgofunct%2Fstencil","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgofunct%2Fstencil/lists"}