kirbysayshi/vash

@foreach razor syntax

Closed this issue · 3 comments

Hi,

First of all, thanks a lot for this great template engine.
It helps a lot to build views, completely separated from the backend.

I just wanted to raise the question why you didn't implement @foreach, as it is in the razor syntax?
If you want to add it, I have built it in an extension, I can contribute and we can optimize it together if you want?

Regards

Contributions to vash are always welcome! I'd love to see your implementation. Did you do it by directly modifying the library, or something else?

One of the main reasons why I never implemented @foreach was because Vash tries to be "only" JS, and I didn't want to support more APIs than necessary (or have to invent APIs for how to handle JS edge cases that C# doesn't have)

Sure below you find the implementation, I'm sure its not bulletproof and optimized but I'm currently using it in a new repo and it works till now. I'm using vash as a view engine in my frontend repositories for .NET backend implementations which use Razor as view engine. And therefore the goal is on my side to keep the syntax as close to the Razor syntax as possible. The frontend repository then delivers a package which exactly contains the structure .NET needs.

Tell me if your interested in looking further into the @foreach implementation, i'm sure we can optimize it and make it ready for your repo,

read() {
		let html  = fs.readFileSync(this.template).toString(); 
		let viewSplit = html.split('\n');

		var view = "";

		for (var i = 0; i < viewSplit.length; ++i) {
			let line = viewSplit[i];

			line = line.replace(new RegExp('Model(\.)?', 'g'), 'model$1');
			line = line.replace(new RegExp('Html.', 'g'), 'html.');
			line = line.replace(new RegExp('.Raw', 'g'), '.raw');

			if (line.indexOf('@foreach') !== -1) {
				let split = line.trim().split(' ');
				let modelName = split[3].trim().substr(0, split[3].length - 2);
				let propName = split[1];
				
				view += '@' + modelName.toString() + '.forEach(function(' + propName + ')';
				let start = 1;
				if(line.indexOf('{') !== -1){
					view += '{';
					start = 0;
				}

				let bracesCounter = 0;
				for(var j=i+start; j < viewSplit.length; ++j){
					let curLine = viewSplit[j];
					if(curLine.indexOf('{') !== -1)
					{
						bracesCounter++;
					}
					if(curLine.indexOf('}') !== -1)
					{
						bracesCounter--;
					}
					if(bracesCounter === 0){
						viewSplit[j] = viewSplit[j].replace('}', '})');
						break;
					}
				}
			}
			else{
				view += line;
			}

			view += '\n';
		};

		return view;
	}

If I'm reading your example correctly, I think it's too error-prone to rely on within vash. It's effectively a preprocessor step that's doing manual parsing itself, right? I think it might break with an inline foreach.

I'm going to close this, but I'll keep it in mind if I ever decide to add syntax expansion to vash.