Closed zkochan closed 8 years ago
I'm really happy you've got so inspired by the idea of mos!
In your first example, I don't really understand how the code snippet is fetched. Do you put it manually inside the tags and then it is searched up in the project? Hence the full version would be like this:
<!--@snippet(show: { fileName:true, lineNumber: true, commitHash: false } )-->
```js
// convert to an Immutable (Ordered)Set
context.childNodes = OrderedSet.of(...context.childNodes);
// compute each `TreeNode` composing the selector within the context we just created
context.selectors.forEach(selector => {
// an instance of the current node we just constructed a context for
const childNode = new TreeNode(this, selector, context);
// pass off the nodes internal compilation to le instance just created
childNode.compile();
});
``
<!--/@-->
Right now it works a little bit differently. The content of the comment-tags is just the output of the code in the first tag. E.g.
<!‐-@'# ' + package.name-‐>
IMHO, it would be better to not copy-paste code. Maybe the solution would be to write something like
<!--@snippet('./src/StyleTree/TreeWalker.js:123-131', {show: { fileName:true, lineNumber: true, commitHash: false }} )-->
<!--/@-->
Now you might think, what if the file was changed and the snippet is not the same at those lines? That's not a problem, because mos test
will not pass and tell you that one of your templates needs an update. Mos test regenerates your templates and checks whether the new version matches the current one. If the code snippet has changed, mos test will fail and you'll have to either regenerate the markdown or update the snippet source/lines
Regarding the template idea. Could you please create a new issue and elaborate on it? Might be a good idea but it'll be hard to concentrate on 2 things in one thread :smile:
Thx for the quick responce. I was thinking that the opening tag would be in-lined in the source containing the code for the snippet. The opening tag begins capture, the closing tag ends it. Anything in between two tags the README.md
/whatever (ie: the old content of the snippet) gets thrown away. New content gets injected. Your example which specifies the line numbers, I think, kinda defeats the purpose. Personally if I had to manually maintain line numbers, I wouldn't use this feature/package. But I think my idea still works, my example just has some flaws:
<!-- -->
is not a valid escape sequence for comments
.md
? Moreover, where within the .md?
README.md
. mos
scans project for tags which define a snippet matching that id, if it cant find one, then it errors. The uids would probably look something like README::BasicExample
, QuickStart.InstallingReact
, or chaper4/creating-your-first-repository
... anything you wanted. It would be rather unobtrusive when reading the source, allow enough uniqueness to prevent collision, and semantic enough to be able to tell what refers to what.So the example would really look like this:
README.md
bla bla this is my project
checkout this code
<!--@renderSnippet('xxxx-unique-id-xxx', { show: { fileName:true, lineNumber: true, commitHash: false } })-->
{code that's been escaped/formatted with md, optionally with a caption, gets injected here}
<!--/@-->
sourcecode
// if it's not a function, scan the node
if (!_.isFunction(node)) {
// iterate over keys, split them up into their seperate types
_.forEach(node, (child, key) => {
if (key === 'sculpt' && _.isFunction(child)) { // custom sculpt function, can hijack the current builder
context.builder = child;
} else if (_.isFunction(child)) { // child node has a function for a builder
context.childNodes.push([key, child]);
} else if (_.isPlainObject(child)) { // child node has an object as a builder
context.childNodes.push([key, child]);
} else if (_.isString(child)) { // child node is a string --> it must be a valid {ccsRule: cssValue}
context.styles.push([key, child]);
}
});
} else { // its a function. lets use it to build instead
context.builder = node;
}
//<!--@snippet('xxxx-unique-id-xxx')-->
// convert to an Immutable (Ordered)Set
context.childNodes = OrderedSet.of(...context.childNodes);
// compute each `TreeNode` composing the selector within the context we just created
context.selectors.forEach(selector => {
// an instance of the current node we just constructed a context for
const childNode = new TreeNode(this, selector, context);
// pass off the nodes internal compilation to le instance just created
childNode.compile();
});
//<!--/@-->
}
}
export default TreeWalker;
And then the output would be the same as the example output from my previous post.
And I suppose if you wanted it to scan sourcefiles for the tags, you'd need a glob/regex to let them specify which ones.
mos.json
or .mosrc
{
"scanFiles": "**/*.+{js|md}",
"escapeSeq": "/(<!--(?:(?!-->).)*-->)/"
}
That regex sequence is for html comments (according to SO)
It also lists ones for single line comments, and multi line comments. It shouldn't be too hard to mix them together/google for more to find regexs to support all different kinds of escape sequences --->
that way this remains language agnostic so everybody wins! except for the person who gets to write the regex
Do you really think other file types need this templating? IMHO, for this use case it can work like this
README.md
bla bla this is my project
checkout this code
<!--@snippet('./src/StyleTree/TreeWalker.js#xxxx-unique-id-xxx', { show: { fileName:true, lineNumber: true, commitHash: false } })-->
{code that's been escaped/formatted with md, optionally with a caption, gets injected here}
<!--/@-->
sourcecode
// if it's not a function, scan the node
if (!_.isFunction(node)) {
// iterate over keys, split them up into their seperate types
_.forEach(node, (child, key) => {
if (key === 'sculpt' && _.isFunction(child)) { // custom sculpt function, can hijack the current builder
context.builder = child;
} else if (_.isFunction(child)) { // child node has a function for a builder
context.childNodes.push([key, child]);
} else if (_.isPlainObject(child)) { // child node has an object as a builder
context.childNodes.push([key, child]);
} else if (_.isString(child)) { // child node is a string --> it must be a valid {ccsRule: cssValue}
context.styles.push([key, child]);
}
});
} else { // its a function. lets use it to build instead
context.builder = node;
}
// #xxxx-unique-id-xxx
// convert to an Immutable (Ordered)Set
context.childNodes = OrderedSet.of(...context.childNodes);
// compute each `TreeNode` composing the selector within the context we just created
context.selectors.forEach(selector => {
// an instance of the current node we just constructed a context for
const childNode = new TreeNode(this, selector, context);
// pass off the nodes internal compilation to le instance just created
childNode.compile();
});
// end snippet
}
}
export default TreeWalker;
The snippet function in the readme can contain the custom logic of selecting the snippet named xxxx-unique-id-xxx
from the ./src/StyleTree/TreeWalker.js
file.
Your concept might be better... But it is a pretty huge change.
How do we specify the order in which the files should be analyzed? Seems like the js file should be analyzed before the README, in order to have the snippet in some dictionary by the time the renderSnippet will be executed
Maybe we implement a simpler solution first and then think if the more robust one is needed?
How about a syntax like:
which would result in something like:
Maybe even add a 'template' functionality
You don't really even need to create your own template system. Markdown is so simple, you could pick anything up off the shelf and use it with little difficulty.
And finally, for brevity's sake, if it's just a one liner... what about a self closing tag syntax akin to HTML?Edit: I just realized this wouldn't be possible/feasible because you need the closing tag to determine where the injected content ends upon rewrites.<!--@doThing(param)/@-->
Aw man this is gonna be so cool.