Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<style>/<defs> support #38

Closed
edemaine opened this issue Jun 14, 2019 · 3 comments
Closed

<style>/<defs> support #38

edemaine opened this issue Jun 14, 2019 · 3 comments

Comments

@edemaine
Copy link
Owner

edemaine commented Jun 14, 2019

It would be nice to be able to define global CSS rules via <style> tag, and global objects like gradients via <defs> tag, but we currently don't have anywhere to put global definitions. I see a few options:

  1. A special symbol like global or maybe svgtiler:global (to avoid conflicts) that can contain such definitions.
  2. JS/CS files could define a top-level symbol like global that could be detected (I think) in addition to the main return value (object or function mapping).
  3. JS/CS could make an API call like svgtiler.def(...) or modify API data like svgtiler.defs.push(...).
  4. JS/CS files could write export defs = <defs>...</defs>, now that we support export
  5. New input file type file.svg that can have <defs> (or <symbol>s?) in it, which gets directly included.
  6. Allow individual symbols to include <style> or <defs> tags (outside of <symbol>s, similar to Keys expanding to multiple <symbol>s #33) that get assembled into a global set of definitions, deduplicating CSS rules and defs with identical ids.

The idea for the last option is that rules are often local to the (various versions of) a single symbol, and this way you can just include the rules you need for this particular figure. One example would be if the symbol SVG was extracted from an Illustrator file, which often has a <style> tag. But this also often isn't the case, e.g., all line types might be the same, or the definitions of - and | might share a lot. Not sure what's best...

@edemaine
Copy link
Owner Author

edemaine commented Feb 24, 2020

  • A new approach: allow a new file type, .css, in the command line.
  • We can allow .styl too! The contents (preprocessed by Stylus) go straight into a <style> block.

This makes it easy to run a tileset through different style files, which is how CSS is supposed to work.

  • To make it more challenging: it would be nice if attributeOrStyle could also detect applied CSS rules. This would enable CSS to specify z-index (for <symbol>s), overflow (for <symbol>s), image-rendering (for <image>s), text-anchor (for <text> in LaTeX mode) that impact SVG Tiler's behavior. This seems possible:
    • CSSOM parses the CSS into CSS Object Model (which we could probably do directly in browser, too?).
    • NWSAPI implements rule matching to see which rules apply
    • This jsdom code (along with this submodule) illustrates how we might use this interface to compute property values, fairly easily, though it needs more work to implement specificity.
    • Perhaps it's worth building a separate package that implements specificity on top of CSSOM and NWSAPI to automatically apply CSS rules to a given DOM node? I need it to work with xmldom, though perhaps other DOMs could also be supported.

Still no support for <defs> e.g. for gradients or filters though. Perhaps we should add a .defs file type that also gets included as-is in <defs>?

@diomidov
Copy link

diomidov commented Aug 23, 2022

Sometimes I want to use a <marker> or <clipPath> in my symbol, where the shape depends on symbol's neighbors. Currently I have to make sure that they have distinct names, which is a pain.

Possible solution: an svgtiler.addDef(...) function which takes an svg ovject such as <symbol>/<marker>/<clipPath>/etc, adds it to the global <defs> with a unique id if it is not already there, and returns that id.

@edemaine
Copy link
Owner Author

edemaine commented Aug 23, 2022

Nice idea!

Alternatively, we could use the export defs = <defs>...</defs> option, and automatically remove any symbols/markers/etc. that aren't referred to via href.

Oh, but I see your point is to automatically generate unique IDs for dynamic markers inside symbols (and in particular in components/helper functions used in symbols, so also doesn't make sense to add a <defs> within each <symbol>). That is definitely an advantage of your approach!

So here's the proposed API:

id = svgtiler.def(<clipPath><polygon .../></clipPath>)
#or
id = svgtiler.def("<clipPath><polygon .../></clipPath>")
  • Moves <clipPath> tag to the global <defs>, re-using existing clipPath if identical SVG content (just like existing <symbol> deduplicator).
  • Automatically adds id to <clipPath> tag and returns it, so this symbol/helper function can <use> it
  • Maybe allow <clipPath id="foo"> to make "natural" IDs like "foo_v1" (following the existing id generation protocol); default could be "_def" or maybe "_clipPath". But need to avoid ambiguity in the case of a symbol also called foo (maybe fine, this will just increase the v number).
  • Maybe delete any such <defs> that don't get <use>d
  • If we want to define global defs, we'd most naturally put this in the beforeDrawing callback. Much more natural would be to allow def to be called global in the definition file (probably with manual id would be best), and whenever it gets <use>d, it also gets copied into <defs> for this drawing. With previous bullet, this is equivalent to: global def calls always get added to <defs> for all subsequent drawings (but will be removed if unused).
    • Beware duplicate keys here; when loading the mapping file we don't have an obvious place to store that this id is used. Maybe we should have a global place to put it, that's inherited by each drawing?
    • Easier alternative is to declare <clipPath/> object globally, and wrap in svgtiler.def upon use.
  • In cases where you want to draw an object and later <use> it (presumably in the same symbol), we could offer svgtiler.id(optionalPrefix). This would avoid duplicate ids e.g. with dynamic symbols or conflicting with other uses of the id. No deduplication though, but gives ability to "manually" work with id and <use>.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants