rtomayko / tilt

Generic interface to multiple Ruby template engines
http://github.com/rtomayko/tilt
Other
1.95k stars 226 forks source link

API method for "registered extensions" #228

Open nyarly opened 10 years ago

nyarly commented 10 years ago

A tool I've been writing uses Tilt to manage it template handling, but needs to route method calls to it based on file extension. I was using the keys of Tilt::mappings before 2.0, and am looking at Tilt::default_mappings.template_map/lazy_map now.

What I'm hoping for is a stable API for accessing the registered template mappings. I only need the extensions that Tilt expects, but I imagine it might also be useful to know what template types Tilt can handle as well.

judofyr commented 9 years ago

Public methods for already-available-template-classes and attempt-to-load-everything-that's-lazy-loadable will come it Tilt 2.1.

judofyr commented 8 years ago

@nyarly do you still need this?

nyarly commented 8 years ago

The use case is https://github.com/nyarly/valise/blob/master/lib/valise/adapters/tilt.rb#L81

I'm more than happy to make use of whatever interface is available to provide the functionality - it sounds like "load everything" followed by "iterate available template classes, mapping to their extensions" would do the job. The existing solution I knew was digging into Tilt's guts, which was what motivated the original question.

judofyr commented 8 years ago

What's a sensible API?

I was thinking:

Not sure about the name of the last one.

nyarly commented 8 years ago

I'd be fine with that.

By analogy to Rails, maybe Tilt::Mapping#eager_load_templates

judofyr commented 8 years ago

I'd accept a pull request for this feature. Otherwise I'll queue it up for later OSS work.

mojavelinux commented 6 years ago

The API that is currently used for this is Tilt.default_mapping#extensions_for. Middleman uses it to determine which extensions to process for a given extension class. Something like:

template_class = Tilt[ext]
all_exts = Tilt.default_mapping.extensions_for(template_class)

The problem with this approach is that for mappings that are loaded lazily, this returns duplicate values. Take the AsciiDoc extensions for example:

require 'tilt'
Tilt.default_mapping.extensions_for(Tilt::AsciidoctorTemplate)
=> ["ad", "adoc", "asciidoc"]
Tilt['adoc']
=> Tilt::AsciidoctorTemplate
Tilt.default_mapping.extensions_for(Tilt::AsciidoctorTemplate)
=> ["adoc", "ad", "adoc", "asciidoc"]

I think the extensions_for method should return a uniq result. I plan to file a PR with this change. See #324.

jkowens commented 5 years ago

Would love to see this API added in a 2.1 release as it would be really useful for Sinatra. See https://github.com/sinatra/sinatra/issues/1172.

jkowens commented 5 years ago

After further investigation, I think what is needed is a method that returns a Tilt class name (String) for a particular template engine without loading the file. It looks like we can do that with something like this:

Tilt.lazy_map[engine].fetch(0, [])[0]
judofyr commented 5 years ago

After further investigation, I think what is needed is a method that returns a Tilt class name (String) for a particular template engine without loading the file.

What's the input and output here? What are you trying to solve? I can imagine multiple different APIs:

jkowens commented 5 years ago

Input would be an engine, and output the string name of a template class. Similar to Tilt.template_for but without class loading.

lookup_template_for("erubis") # => "Tilt::ErubisTemplate"

jeremyevans commented 2 years ago

Considering you can already get this via Tilt's public API (https://github.com/rtomayko/tilt/issues/228#issuecomment-523518301), I think we should close this. However, be aware that just because there is an entry in lazy_map, doesn't mean the entry is usable (https://github.com/rtomayko/tilt/issues/331#issuecomment-1204476651).

judofyr commented 2 years ago

Note that the lazy_map is private (from an API breakage point of view): https://github.com/rtomayko/tilt/blob/686cafab78f17ab04c82036ffb29db26ecad15f3/lib/tilt.rb#L16-L19. The main reason we expose it is for testing the ordering they are registered. I'd prefer to provide a proper API (through a method) than making users use lazy_map directly.

Input would be an engine, and output the string name of a template class. Similar to Tilt.template_for but without class loading.

lookup_template_for("erubis") # => "Tilt::ErubisTemplate"

However, I'm kinda struggling to see the use case here. This will always return the first entry in the lazy map and you have no idea if that is the actual template class which is going to be used. I'd understand if it returned all possible template classes it would attempt to load, but returning the first one doesn't seem useful.