lsegal / yard

YARD is a Ruby Documentation tool. The Y stands for "Yay!"
http://yardoc.org
MIT License
1.94k stars 397 forks source link

Link external documentations #1121

Closed FranklinYu closed 1 month ago

FranklinYu commented 7 years ago

This is a feature request.

Is it possible to link to another project in http://www.rubydoc.info, or to the standard documentation like http://www.ruby-doc.org?

lsegal commented 6 years ago

@franklinyu you can use Markdown or RDoc style links in docstrings to link. There was an issue a little while back that alluded to supporting this type of thing, but it's fairly complex. You could theoretically write a plugin to redirect object references with a given prefix to a specific base URL, which would be generally less complicated but would require much more manual configuration, which is not ideal.

FranklinYu commented 6 years ago

questions

you can use Markdown or RDoc style links in docstrings to link.

I understand that I can use Markdown style link in text area, like

# Get the foo [`String`](http://ruby-doc.org/core-2.4.2/String.html)
def foo
  'foo'
end

but it would be great if it also works directly in types:

# @return [String] the foo string.
def foo
  'foo'
end

Or did you mean this:

# @return [String](http://ruby-doc.org/core-2.4.2/String.html) the foo string
def foo
  'foo'
end

? (I don't think this works currently.)

You could theoretically write a plugin to redirect object references with a given prefix to a specific base URL,

That sounds feasible, like "find everything in Rack::Cors namespace here"?

ideas

If you like this idea, I guess I can start by first generating a list of all the local classes (maybe also modules?), so we can have a map from the class to its URL. If the file is missing online, we can allow user to optionally fallback to specifying a local file. This is how Java did it, as far as I know.

DanRathbun commented 2 years ago

I am wanting this feature as well.

As an example of what I envisioned as a link to a Ruby Core object in the core docs or in a separate YARD project documentation for the Ruby Core ...

Our API modifies the Ruby Core {ruby:String} class by adding these nifty methods:
# A bulleted list follows with normal curly links into the local project YARD docs ...

The {ruby:Object} link would link to the core project that would need to be specified somehow.

I was brainstorming an option for use in the yardopts file:

--link-base prefix:BASE_URL

so the above might be similar to:

--link-base ruby:ruby-doc.org/core-2.7.2/

For {ruby:Object} to work in this simple scenario the valid page needs to be named "Object.html".

This could work for simple linking to external sites.

An option like:

--link-base ruby_primer:ruby-doc.org/core-2.7.2/doc/syntax/

Could be used by a link such as:

See the primer on {ruby_primer:refinements_rdoc Refinements} for more information.

But the Ruby core anchors to methods have special anchor formats. (See my JS attempt below.) It also uses hex values for non-alpha characters in method names (<<, =, +, etc.) I hadn't yet even gotten to the point of converting these characters.


I first attempted doing some dynamic link building, with inline <a class="ruby-link" onClick="ruby()">, ... but it did not work out well. YARD just rendered the inline HTML as plain text.

Ie:

    var ruby_version = 'core-2.7.2/';

    function ruby() {
      var base_url = 'https://ruby-doc.org/';
      var link = this.value;
      if ( link == 'Ruby' ) {
        window.location.href= base_url.concat(ruby_version);
      } else {
        // #method-c-name for class methods
        // #method-i-name for instance methods
        parts = link.split('#');
        if (parts.size > 1) {
          var obj = parts[0];
          var i_meth = parts[1];
          var url = base_url.concat(ruby_version,obj,'.html#method-i-',i_meth);
          window.location.href= url;
        } else {
          // Check for class method:
          parts = link.split('.');
          if (parts.size > 1) {
            var obj = parts[0];
            var c_meth = parts[1];
            var url = base_url.concat(ruby_version,obj,'.html#method-c-',c_meth);
            window.location.href= url;
          } else {
            window.location.href= base_url.concat(ruby_version,link,'.html');
          }
        }
      }
    }

Weirdly, YARD's markdown parser will ignore most embedded HTML unless it has a <p> ... </p> wrapped around it. One exception to the rule seems to be <ul> elements.

lsegal commented 2 years ago

--link-base ruby:ruby-doc.org/core-2.7.2/

This would require users define up-front where objects link by specific versions, which is extremely brittle. For example, if you published a gem with the above in a .yardopts file, that specific gem version would continue linking to the same Ruby 2.7.2 documentation years later, even now as that version is already considered outdated.

The challenge here is providing a mechanism for linking to objects in a way that is abstracted from the location of those objects. Even "Ruby core" classes can eventually be extracted to separate gems (there are plenty of recent Ruby-core examples that were moved out of stdlib in Ruby 3) which would break linking down the line.

More importantly, the relevant "Object" documentation is actually based on the context / environment that your downstream users are in, i.e., users may actually be using Ruby 2.3, so even just linking to "the latest" Object documentation is not exactly accurate. And this doesn't even begin to cover the complexity around dependent gems / third-party libraries with major version bumps.

This is the fundamental problem with "external documentation". YARD's core codebase will likely stay out of trying to solve this problem unless there can be some guarantee of accuracy of information, otherwise this becomes a huge maintenance burden for this project to manage. Until then, this is best done in a third-party plugin or extension that can move faster than YARD's core codebase.

Weirdly, YARD's markdown parser will ignore most embedded HTML unless it has a <p> ... </p> wrapped around it. One exception to the rule seems to be <ul> elements.

YARD doesn't parse Markdown, your Markdown processor library does. This behavior, however, is part of the Markdown "specification", namely, inline HTML can only be used if surrounded by block-level tags-- in other words, you can't use <a> tags within regular Markdown paragraphs, you must escape to unprocessed HTML blocks.

You should technically not be embedding HTML into Markdown but rather use regular markdown links and adjust them appropriately. One easy way to do this would be to detect by schemes. The following Markdown [Object](ruby://Object) would generate the HTML <a href="ruby://Object">Object</a> which you can use the above JS code to rewrite on load. The same would work for YARD's brace syntax: {ruby://Object Object}, though as mentioned in #1410, you should typically not use YARD's linking syntax for bare URLs if your markup processor has its own linking syntax.

DanRathbun commented 2 years ago

This would require users define up-front where objects link by specific versions, which is extremely brittle. For example, if you published a gem with the above in a .yardopts file, that specific gem version would continue linking to the same Ruby 2.7.2 documentation years later, even now as that version is already considered outdated.

I am a not gem author.

I am linking to specific Ruby versions that are distributed as an embedded Ruby scripting engine within an application process. The version of Ruby that is distributed, only gets upgraded every 3 years or so.

The generated YARD docs are for this application's embedded API only. The world of gems is a non-issue.

That said, ... I know it is brittle for the rest of the Ruby world. I'm brainstorming here.

Please do not discount the idea based upon links to a specific Ruby version core doc URL.

Anyway .. since the version only gets updated every 3 to 4 years ... and the YARD docs are regenerated whenever even a minor release adds or fixes API features (ie, at the least the Release Notes need to be updated and pushed,) ... the configuration file (.yardopts) that controls the generation of the API documentation seems a nice central place to change the Ruby version for links to the Ruby version that shipped with the latest release of the application.

Keep in mind that we don't run YARD or generate the docs from within the application's embedded Ruby. We run in a system Ruby install. I just happen to be running YARD in the same Ruby version (2.7.2) that the application uses. But I have newer versions of Ruby installed on my system.

P.S. - The application is likely to not be upgraded to Ruby 3.x for another year.

More importantly, the relevant "Object" documentation is actually based on the context / environment that your downstream users are in, i.e., users may actually be using Ruby 2.3, so even just linking to "the latest" Object documentation is not exactly accurate.

Well we never used v2.3, but did 2.0.0, 2.2.4, 2.5.1, 2.5.5, 2.7.1 and now 2.7.2. Yes some users who decided to stay with there old perpetual licenses will be on older versions, but extension developers need to choose what they will support. Really the user base on the last 3 supported versions would be using Ruby 2.5.5 and up. These versions are subscription license and they really should be upgrading for free to the latest using Ruby 2.7.2. But some users lag behind in upgrading, they are too busy the current version works, etc. They find excuses.

Anyway ... I did go through the testing to generate API documentation for multiple versions using multiple Ruby versions (starting with 1.8.5) but it got too complicated. (This was a scenario where I had a .yardopts file for each API version.)

As I said I had wanted a more dynamic way to choose the Ruby version. I was thinking of sticking a dropdown picklist somewhere at the top of each page. But then I'd need to pass that version value from page to page.

Yes it has happened that new coders using the free version which still uses Ruby 2.2.4 tried to write code that used some method for Array (I think) that was added later post 2.5.

This is why I wanted to perhaps allow the reader of the API docs to choose their Ruby poison version, maybe save it in cookie or something, so that any links to Ruby docs would not "mislead" them.

And this doesn't even begin to cover the complexity around dependent gems / third-party libraries with major version bumps.

This doesn't apply to our situation. Gems are not supported. Extension authors must supply gems or libraries rewrapped in their own namespace module. It's a shared embedded Ruby process so most gems or libraries cannot go modifying core classes.

YARD's core codebase will likely stay out of trying to solve this problem unless there can be some guarantee of accuracy of information, otherwise this becomes a huge maintenance burden for this project to manage. Until then, this is best done in a third-party plugin or extension that can move faster than YARD's core codebase.

Oh, sure I agree with this. When we post desires here it's not that we insist upon core YARD changes. We are just looking for help because YARD is quite complex if you are not into it all of the time. The last time I created a template was 6 years ago. I have to go relearn everything now. And I'm not adverse to learning how to make a plugin.

Regarding accuracy of the external information, that is the documentation authors responsibility.

Forget the Ruby Core doc links angle for a minute.

The other major "category" on external link is to a separate repository that is also under the control of the current one. It's just that they must be separate for maintenance purposes. Or, ... one is the API, and the other might be wholly informational, such as a book of tutorials, programmer guide, etc. that needs to link into the API documentation's classes and methods. This is a part of what I am now doing as a test. But all these informational files are bloating the extra files section. They have to be in the same project now to generate the links, lacking the external link feature. This is a proof of concept, but I know what "they" will say. That they do not want the API documentation bloated this way because it's likely to need too many updates. They want purely educational resources to be separate.


YARD doesn't parse Markdown, your Markdown processor library does. This behavior, however, is part of the Markdown "specification", namely, inline HTML can only be used if surrounded by block-level tags-- in other words, you can't use <a> tags within regular Markdown paragraphs, you must escape to unprocessed HTML blocks.

Yes you're correct I did read this on StackOverflow I think. Slipped my mind.

You should technically not be embedding HTML into Markdown but rather use regular markdown links and adjust them appropriately.

Only when I have to. And some of it was because of that darned Rdoc parser. I think that Red Carpet is going to be much better.

The other impetus for inserting html via {include:file:somesuch.html} is just quick testing for later. This html would become part of a YARD template.

One easy way to do this would be to detect by schemes. The following Markdown [Object](ruby://Object) would generate the HTML <a href="ruby://Object">Object</a> which you can use the above JS code to rewrite on load.

Hmmm.. interesting idea. I'll think on that. I really was hoping later to have a YARD template do the work. But anything is better than having hardcoded URLs to explicit ruby version docs scattered throughout multiple files.

... you should typically not use YARD's linking syntax for bare URLs if your markup processor has its own linking syntax.

Well, I did that because the Rdoc parser was interfering with YARD curly brace linking if I used normal markdown links. I am hoping that issue is resolved with Red Carpet.

DanRathbun commented 2 years ago

It occurred to me again why I was using YARD curly brace links (instead of normal markdown links) and that is that these specific links are Ruby object links and need to be wrapped in a <span> with the object_link CSS class.

This will also apply to the scenario of linking to external YARD documentation. Currently YARD does not create "object link" styled <a> elements when a URL is supplied.