{"id":37017046,"url":"https://github.com/dbmdz/solr-ocrpayload-plugin","last_synced_at":"2026-01-14T01:57:06.259Z","repository":{"id":57730401,"uuid":"136629306","full_name":"dbmdz/solr-ocrpayload-plugin","owner":"dbmdz","description":"Efficient indexing and retrieval of OCR bounding boxes in Solr","archived":true,"fork":false,"pushed_at":"2019-03-13T17:05:44.000Z","size":195,"stargazers_count":22,"open_issues_count":0,"forks_count":2,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-07-13T18:37:16.523Z","etag":null,"topics":["ocr","search","solr-plugin"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"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/dbmdz.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2018-06-08T14:27:30.000Z","updated_at":"2023-01-28T18:46:15.000Z","dependencies_parsed_at":"2022-09-13T08:41:41.590Z","dependency_job_id":null,"html_url":"https://github.com/dbmdz/solr-ocrpayload-plugin","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/dbmdz/solr-ocrpayload-plugin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbmdz%2Fsolr-ocrpayload-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbmdz%2Fsolr-ocrpayload-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbmdz%2Fsolr-ocrpayload-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbmdz%2Fsolr-ocrpayload-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dbmdz","download_url":"https://codeload.github.com/dbmdz/solr-ocrpayload-plugin/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbmdz%2Fsolr-ocrpayload-plugin/sbom","scorecard":{"id":329021,"data":{"date":"2025-08-11","repo":{"name":"github.com/dbmdz/solr-ocrpayload-plugin","commit":"85ce435a29ec5257a7856ea4de7a46eb30099f3b"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":2,"reason":"Found 3/13 approved changesets -- score normalized to 2","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"project is archived","details":["Warn: Repository is archived."],"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact 0.2.1 not signed: https://api.github.com/repos/dbmdz/solr-ocrpayload-plugin/releases/12132548","Warn: release artifact 0.2 not signed: https://api.github.com/repos/dbmdz/solr-ocrpayload-plugin/releases/11789125","Warn: release artifact 0.1 not signed: https://api.github.com/repos/dbmdz/solr-ocrpayload-plugin/releases/11392307","Warn: release artifact 0.2.1 does not have provenance: https://api.github.com/repos/dbmdz/solr-ocrpayload-plugin/releases/12132548","Warn: release artifact 0.2 does not have provenance: https://api.github.com/repos/dbmdz/solr-ocrpayload-plugin/releases/11789125","Warn: release artifact 0.1 does not have provenance: https://api.github.com/repos/dbmdz/solr-ocrpayload-plugin/releases/11392307"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: containerImage not pinned by hash: example/solr/Dockerfile:1: pin your Docker image by updating solr:7.3.1-alpine to solr:7.3.1-alpine@sha256:e761b8931422fcabd9bbad23cef4e498aae4af20e6b68bacb919a8f0be8e2deb","Info:   0 out of   1 containerImage dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 20 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-18T03:08:38.024Z","repository_id":57730401,"created_at":"2025-08-18T03:08:38.024Z","updated_at":"2025-08-18T03:08:38.024Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408704,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"ssl_error","status_checked_at":"2026-01-14T01:40:32.775Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["ocr","search","solr-plugin"],"created_at":"2026-01-14T01:57:05.467Z","updated_at":"2026-01-14T01:57:06.254Z","avatar_url":"https://github.com/dbmdz.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# :construction: Deprecated in favor of [solr-ocrhighlighting](https://github.com/dbmdz/solr-ocrhighlighting)\n\n# Solr OCR Coordinate Payload Plugin\n\n[![Javadocs](https://javadoc.io/badge/de.digitalcollections.search/solr-ocrpayload-plugin.svg)](https://javadoc.io/doc/de.digitalcollections.search/solr-ocrpayload-plugin)\n[![Build Status](https://img.shields.io/travis/dbmdz/solr-ocrpayload-plugin/master.svg)](https://travis-ci.org/dbmdz/solr-ocrpayload-plugin)\n[![Codecov](https://img.shields.io/codecov/c/github/dbmdz/solr-ocrpayload-plugin/master.svg)](https://codecov.io/gh/dbmdz/solr-ocrpayload-plugin)\n[![MIT License](https://img.shields.io/github/license/dbmdz/solr-ocrpayload-plugin.svg)](LICENSE)\n[![GitHub release](https://img.shields.io/github/release/dbmdz/solr-ocrpayload-plugin.svg)](https://github.com/dbmdz/solr-ocrpayload-plugin/releases)\n[![Maven Central](https://img.shields.io/maven-central/v/de.digitalcollections.search/solr-ocrpayload-plugin.svg)](https://search.maven.org/search?q=a:solr-ocrpayload-plugin)\n\n*Efficient indexing and bounding-box \"highlighting\" for OCR text*\n\n## tl;dr\n\n- Store OCR bounding box information and token position directly in the Solr index in a space-efficient manner\n- Retrieve bounding box and token position directly in your Solr query results, no additional parsing necessary\n\n**Indexing**:\n\nThe OCR information is appended after each token as a concatenated list of `\u003ckey\u003e:\u003cval\u003e` pairs, see further down\nfor a detailed description of available keys.\n\n`POST /solr/mycore/update`\n\n```json\n[{ \"id\": \"test_document\",\n   \"ocr_text\": \"this|p:13,l:5,n:6,x:11.1,y:22.2,w:33.3,h:44.4 is|p:13,l:5,n:7,x:22.2,y:33.3,w:44.4,h:55.5 a|p:13,l:5,n:8,x:33.3,y:33.3,w:44.4,h:55.5 test|p:13,l:5,n:9,x:44.4,y:33.3,w:44.4h:55.5\" }]\n```\n\n**Querying**:\n\nThe plugin adds a new top-level key (`ocr_highlight` in this case) that contains the OCR information for\neach matching token as a structured object.\n\n`GET /solr/mycore/select?ocr_hl=true\u0026ocr_hl.fields=ocr_text\u0026indent=true\u0026wt=json\u0026q=test`\n\n```json\n{\n  \"responseHeader\": \"...\",\n  \"response\": {\n    \"numFound\": 1,\n    \"docs\": [{\"id\": \"test_document\"}]\n  },\n  \"ocr_highlight\":{\n    \"test_document\":{\n      \"ocr_text\":[{\n          \"term\":\"test\",\n          \"page\":13,\n          \"line\": 5,\n          \"word\": 9,\n          \"x\":0.444,\n          \"y\":0.333,\n          \"width\":0.444,\n          \"height\":0.555}]\n    }\n  }\n}\n```\n\n## Use Case\nAt the Bavarian State Library, we try to provide full-text search over all of our OCRed content. In addition\nto obtaining matching documents, the user should also get a small snippet of the corresponding part of the\npage image, with the matching words highlighted, similar to what e.g. Google Books provides.\n\n\n## Approaches\nFor this to work, we need some way of mapping matching tokens to their corresponding location in the underlying\nOCR text. A common approach used by a number of libraries is to **use a secondary microservice for this** that takes\nas input a document identifier and a text snippet and will return all coordinates of matching text snippets on\nthe page. While this approach generally works okay, it has several drawbacks:\n\n- **Performance:** Every snippet requires a query to the OCR service, which itself has to do a linear scan\n  through the OCR document. For e.g. a result set of 100 snippets, this will result in 101 queries (initial\n  Solr query and 100 snippet queries). Of course this can be optimized by batching and having a good index\n  structure for the coordinate lookup, but it's still less than ideal.\n- **Storage:** To reliably be able to map text matches to the base text, you have to store a copy of the\n  full text in the index, alongside the regular index. This blows up the index size significantly.\n  Foregoing storing the text and only using the normalized terms from the index for matching will\n  break the mapping to OCR, since depending on the analyzer configuration, Lucene will perform stemming, etc.\n  \nAlternatively, you could also **store the coordinates directly as strings in the index**. This works by e.g.\nindexing each token as `\u003ctoken\u003e|\u003ccoordinates\u003e` and telling Lucene to ignore everything after the pipe during\nanalysis. As the full text of the document is stored, you wil get back a series of these annotated tokens\nas query results and can then parse the coordinates from your highlighting information. This solves the\n*Performance* part of the above approach, but worsens the *Storage* problem: For every token, we now not only\nhave to store the token itself, but an expensive coordinate string as well.\n\n## Our Approach\n\nThis plugin uses a similar approach to the above, but solves the *Storage* problem by using an efficient binary\nformat to store the OCR coordinate information in the index: We use bit-packing to combine a number of OCR\ncoordinate parameters into a **byte payload**, which is not stored in the field itself, but as an associated\n[Lucene Payload](https://lucidworks.com/2017/09/14/solr-payloads/):\n\n- `x`, `y`, `w`, `h`: Coordinates of the bounding box on the page as either:\n    - **absolute** unsigned integer offsets between 0 and `2^coordinateBits` (see below)\n    - **relative** floating point percentages between 0 and 100 (e.g. `x:42.3` for a horizontal offset of 43.2%)\n- `pageIndex`: Unsigned integer that stores the page index of a token (optional)\n- `lineIndex`: Unsigned integer that stores the line index of a token (optional)\n- `wordIndex`: Unsigned integer that stores the word index of a token (optional)\n\nFor each of these values, you can configure the number of bits the plugin should use to store them, or disable\ncertain parameters entirely. This allows you to fine-tune the settings to your needs. In our case, for example, we\nuse these values: `4 * 12 bits (coordinates) + 9 bits (word index) + 11 bits (line index) + 12 bits (page index)`,\nresulting in a 80 bit or 10 byte payload per token. A comparable string representation `p0l0n0x000y000w000h000`\nwould have at least 22 bytes, so we save \u003e50% for every token.\n\nAt query time, we then retrieve the payload for each matching token and put the decoded information into the\n`ocr_highlight` result key that can be directly used without having to do any additional parsing.\n\n## Usage\n### Installation\n\nDownload the [latest release from GitHub](https://github.com/dbmdz/solr-ocrpayload-plugin/releases) and put the JAR into your `$SOLR_HOME/$SOLR_CORE/lib/` directory.\n\n### Indexing configuration\n\nTo use it, first add the `DelimitedOcrInfoPayloadTokenFilterFactory`☕ filter to your analyzer chain (e.g. for a `ocr_text` field type):\n\n```xml\n\u003cfieldtype name=\"text_ocr\" class=\"solr.TextField\" omitTermFreqAndPositions=\"false\"\u003e\n  \u003canalyzer\u003e\n    \u003ctokenizer class=\"solr.WhitespaceTokenizerFactory\"/\u003e\n    \u003cfilter class=\"de.digitalcollections.lucene.analysis.util.DelimitedOcrInfoPayloadTokenFilterFactory\"\n            delimiter=\"☞\" absoluteCoordinates=\"false\" coordinateBits=\"10\" wordBits=\"0\" lineBits=\"0\" pageBits=\"12\" /\u003e\n    \u003cfilter class=\"solr.StandardFilterFactory\"/\u003e\n    \u003cfilter class=\"solr.LowerCaseFilterFactory\"/\u003e\n    \u003cfilter class=\"solr.StopFilterFactory\"/\u003e\n    \u003cfilter class=\"solr.PorterStemFilterFactory\"/\u003e\n  \u003c/analyzer\u003e\n\u003c/fieldtype\u003e\n```\n\nThe filter takes the following parameters:\n\n- `delimiter`: Character used for delimiting the payload from the token in the input document (default: `|`)\n- `absoluteCoordinates`: `true` or `false` to configure whether the stored coordinates are absolute\n- `coordinateBits`:  Number of bits to use for encoding OCR coordinates in the index. (mandatory)\u003cbr/\u003e\n   A value of `10` (default) is recommended, resulting in coordBits to approximately two decimal places.\n- `wordBits`: Number of bits to use for encoding the word index.\u003cbr/\u003e\n   Set to 0 (default) to disable storage of the word index.\n- `lineBits`: Number of bits to use for encoding the line index.\u003cbr/\u003e\n   Set to 0 (default) to disable storage of the line index.\n- `pageBits`: Number of bits to use for encoding the page index.\u003cbr/\u003e\n   Set to 0 (default) to disable storage of the page index.\n\nThe filter expects an input payload after the configured `delimiter` in the input stream, with the payload being a\npseudo-JSON structure (e.g. `k1:1,k2:3`) with the following keys:\n\n- `p`: Page index (if `pageBits` \u003e 0)\n- `l`: Line index  (if `lineBits` \u003e 0)\n- `n`: Word index (if `wordBits` \u003e 0)\n- `x`, `y`, `w`, `h`: Coordinates of the OCR box as floating point percentages or integers (if `absoluteCoordinates`)\n\nAs an example, consider the token `foobar` with an OCR box of `(0.50712, 0.31432, 0.87148, 0.05089)`\n(i.e. with `absoluteCoordinates=\"false\"`), the configured delimiter `☞` and storage of indices for the word (`30`),\nline (`12`) and page (`13`):\n`foobar☞p:13,l:12,n:30,x:50.7,y:31.4,w:87.1,h:5.1`.\n\nAlternatively, with `absoluteCoordinates=\"true\"`, an OCR box of `(512, 1024, 3192, 256)` and otherwise the same\nsettings:\n`foobar☞p:13,l:12,n:30,x:512,y:1024,w:3192,h:256`.\n\nFinally, you just have to configure your schema to use the field type defined above. Storing the content is **not**\nrecommended, since it significantly increases the index size and is not used at all for querying and highlighting:\n\n```xml\n\u003cfield name=\"ocr_text\" type=\"text_ocr\" indexed=\"true\" stored=\"false\" /\u003e\n```\n\n### Highlighting configuration\n\nTo enable highlighting using the OCR payloads, add the `OcrHighlighting` component to your Solr\nconfiguration, configure it with the same `absoluteCoordinates`, `coordinateBits`, `wordBits`, `lineBits` and `pageBits`\nvalues that were used for the filter in the analyzer chain:\n\n```xml\n\u003cconfig\u003e\n  \u003csearchComponent name=\"ocr_highlight\"\n                   class=\"de.digitalcollections.solr.plugin.components.ocrhighlighting.OcrHighlighting\"\n                   absoluteCoordinates=\"false\" coordinateBits=\"10\" wordBits=\"0\" lineBits=\"0\" pageBits=\"12\" /\u003e\n                   \n  \u003crequestHandler name=\"standard\" class=\"solr.StandardRequestHandler\"\u003e\n    \u003carr name=\"last-components\"\u003e\n      \u003cstr\u003eocr_highlight\u003c/str\u003e\n    \u003c/arr\u003e\n  \u003c/requestHandler\u003e\n\u003c/config\u003e\n```\n\nNow at query time, you can just set the `ocr_hl=true` parameter, specify the fields you want highlighted via\n`ocr_hl.fields=myfield,myotherfield` and retrieve highlighted matches with their OCR coordinates:\n\n`GET /solr/mycore/select?ocr_hl=true\u0026ocr_hl.fields=ocr_text\u0026indent=true\u0026q=augsburg\u0026wt=json`\n\n```json\n{\n  \"responseHeader\":{\n    \"status\":0,\n    \"QTime\":158},\n  \"response\":{\"numFound\":526,\"start\":0,\"docs\":[\n      {\n        \"id\":\"bsb10502835\"},\n      {\n        \"id\":\"bsb11032147\"},\n      {\n        \"id\":\"bsb10485243\"},\n      ...\n  },\n  \"ocr_highlight\":{\n    \"bsb10502835\":{\n      \"ocr_text\":[{\n          \"page\":7,\n          \"position\":9,\n          \"term\":\"augsburg\",\n          \"x\":0.111,\n          \"y\":0.062,\n          \"width\":0.075,\n          \"height\":0.013},\n        {\n          \"page\":7,\n          \"position\":264,\n          \"term\":\"augsburg\",\n          \"x\":0.320,\n          \"y\":0.670,\n          \"width\":0.099,\n          \"height\":0.012},\n        ...]}},\n       ...\n    }\n  }\n}\n```\n\n\n## FAQ\n\n- **How does highlighting work with phrase queries?**\n  \n  You will receive a bounding box object for every individual matching term in the phrase.\n\n- **What are the performance and storage implications of using this plugin?**\n\n  *Performance*: With an Intel Xeon E5-1620@3.5GHz on a single core, we measured (with JMH):\n  \n  - Encoding the Payload: 1,484,443.200 Payloads/Second or ~14.2MiB/s with an 80bit payload\n  - Decoding the Payload: 1,593,036.372 Payloads/Second or ~15.2MiB/s with an 80bit payload\n  \n  *Storage*: This depends on your configuration. With our sample configuration of an 80 bit payload\n  (see above), the payload overhead is 10 bytes per token. That is, for a corpus size of 10 Million Tokens,\n  you will need approximately 95MiB to store the payloads.\n  The actual storage required might be lower, since Lucene compresses the payloads with LZ4.\n  \n- **Does this work with SolrCloud?**\n\n  It does! We're running it with SolrCloud ourselves.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdbmdz%2Fsolr-ocrpayload-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdbmdz%2Fsolr-ocrpayload-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdbmdz%2Fsolr-ocrpayload-plugin/lists"}