{"id":13519145,"url":"https://github.com/FriendsOfPHP/Sami","last_synced_at":"2025-03-31T12:31:21.259Z","repository":{"id":3293771,"uuid":"4334944","full_name":"FriendsOfPHP/Sami","owner":"FriendsOfPHP","description":"An API documentation generator","archived":true,"fork":false,"pushed_at":"2018-09-13T16:44:29.000Z","size":758,"stargazers_count":2000,"open_issues_count":41,"forks_count":292,"subscribers_count":87,"default_branch":"master","last_synced_at":"2024-04-14T11:54:48.346Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FriendsOfPHP.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-05-15T11:20:10.000Z","updated_at":"2024-04-11T17:20:19.000Z","dependencies_parsed_at":"2022-09-04T01:10:23.553Z","dependency_job_id":null,"html_url":"https://github.com/FriendsOfPHP/Sami","commit_stats":null,"previous_names":[],"tags_count":42,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FriendsOfPHP%2FSami","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FriendsOfPHP%2FSami/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FriendsOfPHP%2FSami/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FriendsOfPHP%2FSami/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FriendsOfPHP","download_url":"https://codeload.github.com/FriendsOfPHP/Sami/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246469169,"owners_count":20782685,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T05:01:54.524Z","updated_at":"2025-03-31T12:31:20.914Z","avatar_url":"https://github.com/FriendsOfPHP.png","language":"PHP","funding_links":[],"categories":["PHP","文档 Documentation","类库","Table of Contents"],"sub_categories":["API文档","Documentation"],"readme":"Sami: an API documentation generator\n====================================\n\n**WARNING**: Sami is not supported nor maintained anymore. Feel free to fork.\n\nCurious about what Sami generates? Have a look at the `Symfony API`_.\n\nInstallation\n------------\n\n.. caution::\n\n    Sami requires **PHP 7**.\n\nGet Sami as a `phar file`_:\n\n.. code-block:: bash\n\n    $ curl -O http://get.sensiolabs.org/sami.phar\n\nCheck that everything worked as expected by executing the ``sami.phar`` file\nwithout any arguments:\n\n.. code-block:: bash\n\n    $ php sami.phar\n\n.. note::\n\n    Installing Sami as a regular Composer dependency is NOT supported. Sami is\n    a tool, not a library. As such, it should be installed as a standalone\n    package, so that Sami's dependencies do not interfere with your project's\n    dependencies.\n\nConfiguration\n-------------\n\nBefore generating documentation, you must create a configuration file. Here is\nthe simplest possible one:\n\n.. code-block:: php\n\n    \u003c?php\n\n    return new Sami\\Sami('/path/to/symfony/src');\n\nThe configuration file must return an instance of ``Sami\\Sami`` and the first\nargument of the constructor is the path to the code you want to generate\ndocumentation for.\n\nActually, instead of a directory, you can use any valid PHP iterator (and for\nthat matter any instance of the Symfony `Finder`_ class):\n\n.. code-block:: php\n\n    \u003c?php\n\n    use Sami\\Sami;\n    use Symfony\\Component\\Finder\\Finder;\n\n    $iterator = Finder::create()\n        -\u003efiles()\n        -\u003ename('*.php')\n        -\u003eexclude('Resources')\n        -\u003eexclude('Tests')\n        -\u003ein('/path/to/symfony/src')\n    ;\n\n    return new Sami($iterator);\n\nThe ``Sami`` constructor optionally takes an array of options as a second\nargument:\n\n.. code-block:: php\n\n    return new Sami($iterator, array(\n        'theme'                =\u003e 'symfony',\n        'title'                =\u003e 'Symfony2 API',\n        'build_dir'            =\u003e __DIR__.'/build',\n        'cache_dir'            =\u003e __DIR__.'/cache',\n        'remote_repository'    =\u003e new GitHubRemoteRepository('username/repository', '/path/to/repository'),\n        'default_opened_level' =\u003e 2,\n    ));\n\nAnd here is how you can configure different versions:\n\n.. code-block:: php\n\n    \u003c?php\n\n    use Sami\\Sami;\n    use Sami\\RemoteRepository\\GitHubRemoteRepository;\n    use Sami\\Version\\GitVersionCollection;\n    use Symfony\\Component\\Finder\\Finder;\n\n    $iterator = Finder::create()\n        -\u003efiles()\n        -\u003ename('*.php')\n        -\u003eexclude('Resources')\n        -\u003eexclude('Tests')\n        -\u003ein($dir = '/path/to/symfony/src')\n    ;\n\n    // generate documentation for all v2.0.* tags, the 2.0 branch, and the master one\n    $versions = GitVersionCollection::create($dir)\n        -\u003eaddFromTags('v2.0.*')\n        -\u003eadd('2.0', '2.0 branch')\n        -\u003eadd('master', 'master branch')\n    ;\n\n    return new Sami($iterator, array(\n        'theme'                =\u003e 'symfony',\n        'versions'             =\u003e $versions,\n        'title'                =\u003e 'Symfony2 API',\n        'build_dir'            =\u003e __DIR__.'/../build/sf2/%version%',\n        'cache_dir'            =\u003e __DIR__.'/../cache/sf2/%version%',\n        'remote_repository'    =\u003e new GitHubRemoteRepository('symfony/symfony', dirname($dir)),\n        'default_opened_level' =\u003e 2,\n    ));\n\nTo generate documentation for a PHP 5.2 project, simply set the\n``simulate_namespaces`` option to ``true``.\n\nYou can find more configuration examples under the ``examples/`` directory of\nthe source code.\n\nSami only documents the public API (public properties and methods); override\nthe default configured ``filter`` to change this behavior:\n\n.. code-block:: php\n\n    \u003c?php\n\n    use Sami\\Parser\\Filter\\TrueFilter;\n\n    $sami = new Sami(...);\n    // document all methods and properties\n    $sami['filter'] = function () {\n        return new TrueFilter();\n    };\n\nRendering\n---------\n\nNow that we have a configuration file, let's generate the API documentation:\n\n.. code-block:: bash\n\n    $ php sami.phar update /path/to/config.php\n\nThe generated documentation can be found under the configured ``build/``\ndirectory (note that the client side search engine does not work on Chrome due\nto JavaScript execution restriction, unless Chrome is started with the\n\"--allow-file-access-from-files\" option -- it works fine in Firefox).\n\nBy default, Sami is configured to run in \"incremental\" mode. It means that when\nrunning the ``update`` command, Sami only re-generates the files that needs to\nbe updated based on what has changed in your code since the last execution.\n\nSami also detects problems in your phpdoc and can tell you what you need to fix\nif you add the ``-v`` option:\n\n.. code-block:: bash\n\n    $ php sami.phar update /path/to/config.php -v\n\nCreating a Theme\n----------------\n\nIf the default themes do not suit your needs, you can very easily create a new\none, or just override an existing one.\n\nA theme is just a directory with a ``manifest.yml`` file that describes the\ntheme (this is a YAML file):\n\n.. code-block:: yaml\n\n    name:   symfony\n    parent: default\n\nThe above configuration creates a new ``symfony`` theme based on the\n``default`` built-in theme. To override a template, just create a file with\nthe same name as the original one. For instance, here is how you can extend the\ndefault class template to prefix the class name with \"Class \" in the class page\ntitle:\n\n.. code-block:: jinja\n\n    {# pages/class.twig #}\n\n    {% extends 'default/pages/class.twig' %}\n\n    {% block title %}Class {{ parent() }}{% endblock %}\n\nIf you are familiar with Twig, you will be able to very easily tweak every\naspect of the templates as everything has been well isolated in named Twig\nblocks.\n\nA theme can also add more templates and static files. Here is the manifest for\nthe default theme:\n\n.. code-block:: yaml\n\n    name: default\n\n    static:\n        'css/sami.css': 'css/sami.css'\n        'css/bootstrap.min.css': 'css/bootstrap.min.css'\n        'css/bootstrap-theme.min.css': 'css/bootstrap-theme.min.css'\n        'fonts/glyphicons-halflings-regular.eot': 'fonts/glyphicons-halflings-regular.eot'\n        'fonts/glyphicons-halflings-regular.svg': 'fonts/glyphicons-halflings-regular.svg'\n        'fonts/glyphicons-halflings-regular.ttf': 'fonts/glyphicons-halflings-regular.ttf'\n        'fonts/glyphicons-halflings-regular.woff': 'fonts/glyphicons-halflings-regular.woff'\n        'js/bootstrap.min.js': 'js/bootstrap.min.js'\n        'js/jquery-1.11.1.min.js': 'js/jquery-1.11.1.min.js'\n        'js/handlebars.min.js': 'js/handlebars.min.js'\n        'js/typeahead.min.js': 'js/typeahead.min.js'\n\n    global:\n        'index.twig':      'index.html'\n        'doc-index.twig':  'doc-index.html'\n        'namespaces.twig': 'namespaces.html'\n        'classes.twig':    'classes.html'\n        'interfaces.twig': 'interfaces.html'\n        'traits.twig':     'traits.html'\n        'opensearch.twig': 'opensearch.xml'\n        'search.twig':     'search.html'\n        'sami.js.twig':    'sami.js'\n\n    namespace:\n        'namespace.twig': '%s.html'\n\n    class:\n        'class.twig': '%s.html'\n\n\nFiles are contained into sections, depending on how Sami needs to treat them:\n\n* ``static``: Files are copied as is (for assets like images, stylesheets, or\n  JavaScript files);\n\n* ``global``: Templates that do not depend on the current class context;\n\n* ``namespace``: Templates that should be generated for every namespace;\n\n* ``class``: Templates that should be generated for every class.\n\n.. _Symfony API: http://api.symfony.com/\n.. _phar file:   http://get.sensiolabs.org/sami.phar\n.. _Finder:      http://symfony.com/doc/current/components/finder.html\n\nSearch Index\n~~~~~~~~~~~~\n\nThe autocomplete and search functionality of Sami is provided through a\nsearch index that is generated based on the classes, namespaces, interfaces,\nand traits of a project. You can customize the search index by overriding the\n``search_index_extra`` block of ``sami.js.twig``.\n\nThe ``search_index_extra`` allows you to extend the default theme and add more\nentries to the index. For example, some projects implement magic methods that\nare dynamically generated at runtime. You might wish to document these methods\nwhile generating API documentation and add them to the search index.\n\nEach entry in the search index is a JavaScript object that contains the\nfollowing keys:\n\ntype\n    The type associated with the entry. Built-in types are \"Class\",\n    \"Namespace\", \"Interface\", \"Trait\". You can add additional types specific\n    to an application, and the type information will appear next to the search\n    result.\n\nname\n    The name of the entry. This is the element in the index that is searchable\n    (e.g., class name, namespace name, etc).\n\nfromName\n    The parent of the element (if any). This can be used to provide context for\n    the entry. For example, the fromName of a class would be the namespace of\n    the class.\n\nfromLink\n    The link to the parent of the entry (if any). This is used to link a child\n    to a parent. For example, this would be a link from a class to the class\n    namespace.\n\ndoc\n    A short text description of the entry.\n\nOne such example of when overriding the index is useful could be documenting\ndynamically generated API operations of a web service client. Here's a simple\nexample that adds dynamically generated API operations for a web service client\nto the search index:\n\n.. code-block:: jinja\n\n    {% extends \"default/sami.js.twig\" %}\n\n    {% block search_index_extra %}\n        {% for operation in operations -%}\n            {\"type\": \"Operation\", \"link\": \"{{ operation.path }}\", \"name\": \"{{ operation.name }}\", \"doc\": \"{{ operation.doc }}\"},\n        {%- endfor %}\n    {% endblock %}\n\nThis example assumes that the template has a variable ``operations`` available\nwhich contains an array of operations.\n\n.. note::\n\n    Always include a trailing comma for each entry you add to the index. Sami\n    will take care of ensuring that trailing commas are handled properly.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FFriendsOfPHP%2FSami","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FFriendsOfPHP%2FSami","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FFriendsOfPHP%2FSami/lists"}